diff --git a/.github/ci-filters.yml b/.github/ci-filters.yml index 5423e3b8329..bbcaf8684ad 100644 --- a/.github/ci-filters.yml +++ b/.github/ci-filters.yml @@ -83,6 +83,9 @@ nix: npm_and_yarn: - *shared - 'npm_and_yarn/**' +nub: + - *shared + - 'nub/**' nuget: - *shared - 'nuget/**' diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b210f1b0936..31bae4ae595 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -127,6 +127,7 @@ updates: directories: - "/bun/helpers" - "/npm_and_yarn/helpers" + - "/nub/helpers" schedule: interval: "weekly" day: "sunday" diff --git a/.github/issue-labeler.yml b/.github/issue-labeler.yml index a25b0645949..a63f6b66847 100644 --- a/.github/issue-labeler.yml +++ b/.github/issue-labeler.yml @@ -93,3 +93,6 @@ "L: sbt": - '(sbt)' + +"L: nub": + - '(nub)' diff --git a/.github/labeler.yml b/.github/labeler.yml index e18fef01a7b..d4a2e494af2 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -51,6 +51,7 @@ - any-glob-to-any-file: - bun/** - npm_and_yarn/** + - nub/** "L: java:gradle": - changed-files: diff --git a/.github/smoke-filters.yml b/.github/smoke-filters.yml index 0666594d08e..6cf16cf1c03 100644 --- a/.github/smoke-filters.yml +++ b/.github/smoke-filters.yml @@ -56,6 +56,9 @@ nix: npm_and_yarn: - *common - 'npm_and_yarn/**' +nub: + - *common + - 'nub/**' nuget: - *common - 'nuget/**' diff --git a/.github/smoke-matrix.json b/.github/smoke-matrix.json index 0ea71686b7e..0e53930faf7 100644 --- a/.github/smoke-matrix.json +++ b/.github/smoke-matrix.json @@ -99,6 +99,11 @@ "test": "npm", "ecosystem": "npm" }, + { + "core": "nub", + "test": "nub", + "ecosystem": "nub" + }, { "core": "nuget", "test": "nuget-resolvability", diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a76d85b285c..28f91a5f254 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,7 @@ jobs: - { path: maven, name: maven, ecosystem: maven } - { path: nix, name: nix, ecosystem: nix } - { path: npm_and_yarn, name: npm_and_yarn, ecosystem: npm } + - { path: nub, name: nub, ecosystem: nub } - { path: nuget, name: nuget, ecosystem: nuget } - { path: opentofu, name: opentofu, ecosystem: opentofu } - { path: pre_commit, name: pre_commit, ecosystem: pre-commit } diff --git a/Dockerfile.updater-core b/Dockerfile.updater-core index 4790916e071..7aae2091dc6 100644 --- a/Dockerfile.updater-core +++ b/Dockerfile.updater-core @@ -167,7 +167,7 @@ COPY --chown=dependabot:dependabot --parents */.bundle */*.gemspec common/lib/de # Entries are either "" (gem lives in a directory matching its name) or # ":" when multiple gems share a directory (e.g. dependabot-docker # and dependabot-docker_compose both ship from docker/). -ARG ECOSYSTEM_LIST="bazel bun bundler cargo composer conda deno devcontainers docker docker_compose:docker dotnet_sdk elm git_submodules github_actions go_modules gradle helm hex julia maven nix npm_and_yarn nuget opentofu pre_commit pub python rust_toolchain sbt silent swift terraform uv vcpkg" +ARG ECOSYSTEM_LIST="bazel bun bundler cargo composer conda deno devcontainers docker docker_compose:docker dotnet_sdk elm git_submodules github_actions go_modules gradle helm hex julia maven nix npm_and_yarn nub nuget opentofu pre_commit pub python rust_toolchain sbt silent swift terraform uv vcpkg" # prevent having all the source in every ecosystem image RUN for entry in $ECOSYSTEM_LIST; do \ name="${entry%%:*}"; \ diff --git a/Gemfile b/Gemfile index 84d9ede6897..30b5f7c8317 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ gem "dependabot-hex", path: "hex" gem "dependabot-julia", path: "julia" gem "dependabot-maven", path: "maven" gem "dependabot-npm_and_yarn", path: "npm_and_yarn" +gem "dependabot-nub", path: "nub" gem "dependabot-nuget", path: "nuget" gem "dependabot-opentofu", path: "opentofu" gem "dependabot-pre_commit", path: "pre_commit" diff --git a/Gemfile.lock b/Gemfile.lock index 81810d30920..0d14cf6cc47 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -152,6 +152,13 @@ PATH dependabot-npm_and_yarn (0.394.0) dependabot-common (= 0.394.0) +PATH + remote: nub + specs: + dependabot-nub (0.394.0) + dependabot-common (= 0.394.0) + dependabot-npm_and_yarn (= 0.394.0) + PATH remote: nuget specs: @@ -498,6 +505,7 @@ DEPENDENCIES dependabot-julia! dependabot-maven! dependabot-npm_and_yarn! + dependabot-nub! dependabot-nuget! dependabot-opentofu! dependabot-pre_commit! @@ -569,6 +577,7 @@ CHECKSUMS dependabot-julia (0.394.0) dependabot-maven (0.394.0) dependabot-npm_and_yarn (0.394.0) + dependabot-nub (0.394.0) dependabot-nuget (0.394.0) dependabot-opentofu (0.394.0) dependabot-pre_commit (0.394.0) diff --git a/bin/docker-dev-shell b/bin/docker-dev-shell index 62b96169602..1f533afb8d1 100755 --- a/bin/docker-dev-shell +++ b/bin/docker-dev-shell @@ -255,6 +255,12 @@ docker run --rm -ti \ -v "$(pwd)/npm_and_yarn/lib:$CODE_DIR/npm_and_yarn/lib" \ -v "$(pwd)/npm_and_yarn/script:$CODE_DIR/npm_and_yarn/script" \ -v "$(pwd)/npm_and_yarn/spec:$CODE_DIR/npm_and_yarn/spec" \ + -v "$(pwd)/nub/.rubocop.yml:$CODE_DIR/nub/.rubocop.yml" \ + -v "$(pwd)/nub/dependabot-nub.gemspec:$CODE_DIR/nub/dependabot-nub.gemspec" \ + -v "$(pwd)/nub/helpers:$CODE_DIR/nub/helpers" \ + -v "$(pwd)/nub/lib:$CODE_DIR/nub/lib" \ + -v "$(pwd)/nub/script:$CODE_DIR/nub/script" \ + -v "$(pwd)/nub/spec:$CODE_DIR/nub/spec" \ -v "$(pwd)/nuget/.rubocop.yml:$CODE_DIR/nuget/.rubocop.yml" \ -v "$(pwd)/nuget/dependabot-nuget.gemspec:$CODE_DIR/nuget/dependabot-nuget.gemspec" \ -v "$(pwd)/nuget/helpers:$CODE_DIR/nuget/helpers" \ diff --git a/bin/dry-run.rb b/bin/dry-run.rb index 4f531bd80fd..0906a5601f1 100755 --- a/bin/dry-run.rb +++ b/bin/dry-run.rb @@ -36,6 +36,7 @@ # - hex # - maven # - npm_and_yarn +# - nub # - nuget # - pip (includes pipenv) # - pre_commit @@ -81,6 +82,7 @@ $LOAD_PATH << "./maven/lib" $LOAD_PATH << "./nix/lib" $LOAD_PATH << "./npm_and_yarn/lib" +$LOAD_PATH << "./nub/lib" $LOAD_PATH << "./nuget/lib" $LOAD_PATH << "./pre_commit/lib" $LOAD_PATH << "./pub/lib" @@ -139,6 +141,7 @@ require "dependabot/julia" require "dependabot/maven" require "dependabot/npm_and_yarn" +require "dependabot/nub" require "dependabot/nuget" require "dependabot/pre_commit" require "dependabot/pub" @@ -390,6 +393,7 @@ hex maven npm_and_yarn + nub nuget pip pre_commit diff --git a/common/lib/dependabot/config/file.rb b/common/lib/dependabot/config/file.rb index 75ff70ae2fe..65766429915 100644 --- a/common/lib/dependabot/config/file.rb +++ b/common/lib/dependabot/config/file.rb @@ -82,6 +82,7 @@ def self.parse(config) "mix" => "hex", "nix" => "nix", "npm" => "npm_and_yarn", + "nub" => "nub", "nuget" => "nuget", "opentofu" => "opentofu", "pip" => "pip", diff --git a/docker-bake.hcl b/docker-bake.hcl index 1e87fd1e4aa..c8dd89701c8 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -38,6 +38,7 @@ variable "ECOSYSTEMS" { { name = "maven", image = "maven", dockerfile = "maven/Dockerfile" }, { name = "nix", image = "nix", dockerfile = "nix/Dockerfile" }, { name = "npm_and_yarn", image = "npm", dockerfile = "npm_and_yarn/Dockerfile" }, + { name = "nub", image = "nub", dockerfile = "nub/Dockerfile" }, { name = "nuget", image = "nuget", dockerfile = "nuget/Dockerfile" }, { name = "pre_commit", image = "pre-commit", dockerfile = "pre_commit/Dockerfile" }, { name = "pub", image = "pub", dockerfile = "pub/Dockerfile" }, diff --git a/nub/.bundle/config b/nub/.bundle/config new file mode 100644 index 00000000000..3faf5cfe5e6 --- /dev/null +++ b/nub/.bundle/config @@ -0,0 +1 @@ +BUNDLE_GEMFILE: "../dependabot-updater/Gemfile" diff --git a/nub/.gitignore b/nub/.gitignore new file mode 100644 index 00000000000..8c96619b722 --- /dev/null +++ b/nub/.gitignore @@ -0,0 +1,7 @@ +/.bundle/* +!.bundle/config +/.env +/tmp +/dependabot-*.gem +/helpers/node_modules +/helpers/install-dir diff --git a/nub/.rubocop.yml b/nub/.rubocop.yml new file mode 100644 index 00000000000..edee67d8bc7 --- /dev/null +++ b/nub/.rubocop.yml @@ -0,0 +1,48 @@ +inherit_from: ../.rubocop.yml + +Sorbet/ForbidTUnsafe: + Exclude: + - lib/dependabot/nub/update_checker.rb + - lib/dependabot/nub/update_checker/latest_version_finder.rb + - lib/dependabot/nub/update_checker/version_resolver.rb + +# The lib below models parsed package.json / npm-registry / lockfile JSON, which is genuinely +# heterogeneous — the same `T::Hash[String, T.untyped]` shapes bun and npm_and_yarn carry. Those +# gems grandfather the identical files under Sorbet/ForbidTUntyped in the root .rubocop_todo.yml; +# nub cannot, because script/sorbet-untyped-ratchet forbids adding NEW files to that list, so the +# exclusion lives here per-gem instead. Same rationale as the RSpec/Lint entries below. +Sorbet/ForbidTUntyped: + Exclude: + - lib/dependabot/nub/dependency_files_filterer.rb + - lib/dependabot/nub/file_fetcher.rb + - lib/dependabot/nub/file_parser.rb + - lib/dependabot/nub/file_parser/lockfile_parser.rb + - lib/dependabot/nub/file_parser/nub_lock.rb + - lib/dependabot/nub/file_updater.rb + - lib/dependabot/nub/file_updater/package_json_updater.rb + - lib/dependabot/nub/metadata_finder.rb + - lib/dependabot/nub/package/package_details_fetcher.rb + - lib/dependabot/nub/package/registry_finder.rb + - lib/dependabot/nub/package_manager.rb + - lib/dependabot/nub/registry_helper.rb + - lib/dependabot/nub/registry_parser.rb + - lib/dependabot/nub/update_checker.rb + - lib/dependabot/nub/update_checker/latest_version_finder.rb + - lib/dependabot/nub/update_checker/library_detector.rb + - lib/dependabot/nub/update_checker/requirements_updater.rb + - lib/dependabot/nub/update_checker/version_resolver.rb + - lib/dependabot/nub/update_checker/vulnerability_auditor.rb + +# ERR_PATTERNS follows a `private` — harmless (constants ignore visibility). bun grandfathers the +# byte-identical bun_lockfile_updater.rb for this cop in the root todo. +Lint/UselessConstantScoping: + Exclude: + - lib/dependabot/nub/file_updater/nub_lockfile_updater.rb + +# Stubbing idioms inherited from bun's update_checker_spec, which bun/npm_and_yarn grandfather. +RSpec/AnyInstance: + Exclude: + - spec/dependabot/nub/update_checker_spec.rb +RSpec/StubbedMock: + Exclude: + - spec/dependabot/nub/update_checker_spec.rb diff --git a/nub/Dockerfile b/nub/Dockerfile new file mode 100644 index 00000000000..9e9ce82b24d --- /dev/null +++ b/nub/Dockerfile @@ -0,0 +1,43 @@ +# syntax=docker.io/docker/dockerfile:1.20 +FROM ghcr.io/dependabot/dependabot-updater-core + +# Check for updates at https://github.com/nubjs/nub/releases +ARG NUB_VERSION=0.8.0 + +# See https://github.com/nodesource/distributions#installation-instructions +ARG NODEJS_VERSION=24 + +# Install Node and nub. +# nub is distributed as @nubjs/nub with per-platform binary optionalDependencies +# (@nubjs/nub-) placed by its postinstall; the container is linux-x64 (glibc). +RUN mkdir -p /etc/apt/keyrings \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODEJS_VERSION}.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + nodejs \ + && rm -rf /var/lib/apt/lists/* \ + && npm install -g @nubjs/nub@$NUB_VERSION \ + && rm -rf ~/.npm + +USER dependabot + +# Use our custom CA bundle. +ENV NODE_EXTRA_CA_CERTS=/etc/ssl/certs/ca-certificates.crt + +# Silence warning messages that aren't useful within the Dependabot context. +# These env vars are consumed by the Dependabot native helpers, which rely on npm/pnpm. +# CAUTION: `NPM_CONFIG_*` vars take precedence over the user's .npmrc settings. For these it always makes sense, but for +# other non-default configs it might be better to set them in a global .npmrc instead so users' .npmrc settings are respected. +ENV NPM_CONFIG_AUDIT=false \ + NPM_CONFIG_FUND=false + +ENV DEPENDABOT_NATIVE_HELPERS_PATH="/opt" +COPY --chown=dependabot:dependabot nub/helpers /opt/nub/helpers +RUN bash /opt/nub/helpers/build + +# nub depends on dependabot-npm_and_yarn (nub.lock is pnpm-lock v9, so nub reuses its +# pnpm-format Ruby classes). The updater-core base only stubs sibling ecosystems, so the +# full npm_and_yarn lib must be copied in — same pattern as pre_commit/Dockerfile. +COPY --chown=dependabot:dependabot --parents nub npm_and_yarn common $DEPENDABOT_HOME/ +COPY --chown=dependabot:dependabot updater $DEPENDABOT_HOME/dependabot-updater diff --git a/nub/README.md b/nub/README.md new file mode 100644 index 00000000000..a4995b2efe6 --- /dev/null +++ b/nub/README.md @@ -0,0 +1,18 @@ +## `dependabot-nub` + +Nub support for [`dependabot-core`][core-repo]. + +### Running locally + +1. Start a development shell + + ``` + $ bin/docker-dev-shell nub + ``` + +2. Run tests + ``` + [dependabot-core-dev] ~ $ cd nub && rspec + ``` + +[core-repo]: https://github.com/dependabot/dependabot-core diff --git a/nub/dependabot-nub.gemspec b/nub/dependabot-nub.gemspec new file mode 100644 index 00000000000..891b011001b --- /dev/null +++ b/nub/dependabot-nub.gemspec @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + common_gemspec = + Bundler.load_gemspec_uncached("../common/dependabot-common.gemspec") + + spec.name = "dependabot-nub" + spec.summary = "Provides Dependabot support for Javascript" + spec.description = "Dependabot-Nub provides support for bumping Javascript libraries via " \ + "Dependabot. " \ + "If you want support for multiple package managers, you probably want the meta-gem " \ + "dependabot-omnibus." + + spec.author = common_gemspec.author + spec.email = common_gemspec.email + spec.homepage = common_gemspec.homepage + spec.license = common_gemspec.license + + spec.metadata = { + "bug_tracker_uri" => common_gemspec.metadata["bug_tracker_uri"], + "changelog_uri" => common_gemspec.metadata["changelog_uri"] + } + + spec.version = common_gemspec.version + spec.required_ruby_version = common_gemspec.required_ruby_version + spec.required_rubygems_version = common_gemspec.required_ruby_version + + spec.require_path = "lib" + spec.files = [] + + spec.add_dependency "dependabot-common", Dependabot::VERSION + # nub.lock is byte-compatible with pnpm-lock v9, so nub reuses npm_and_yarn's + # pnpm-format classes (aliased/subclassed) rather than re-cloning them. + spec.add_dependency "dependabot-npm_and_yarn", Dependabot::VERSION + + common_gemspec.development_dependencies.each do |dep| + spec.add_development_dependency dep.name, *dep.requirement.as_list + end + + next unless File.exist?("../.gitignore") + + spec.files += `git -C #{__dir__} ls-files lib helpers -z`.split("\x0") +end diff --git a/nub/helpers/.eslintrc b/nub/helpers/.eslintrc new file mode 100644 index 00000000000..c45b4828988 --- /dev/null +++ b/nub/helpers/.eslintrc @@ -0,0 +1,11 @@ +{ + "extends": [ + "prettier" + ], + "env": { + "node": true + }, + "parserOptions": { + "ecmaVersion": "latest" + } +} diff --git a/nub/helpers/README.md b/nub/helpers/README.md new file mode 100644 index 00000000000..79a06570caa --- /dev/null +++ b/nub/helpers/README.md @@ -0,0 +1,29 @@ +Native JavaScript helpers +------------------------- + +This directory contains helper functions for npm and yarn, natively written in +Javascript so that we can utilize the package managers internal APIs and other +native tooling for these ecosystems. + +These helpers are called from the Ruby code via `run.js`, they are passed +arguments via stdin and return JSON data to stdout. + +## Testing + +When working on these helpers, it's convenient to write some high level tests in +JavaScript to make it easier to debug the code. + +You can now run the tests from this directory by running: + +``` +yarn test path/to/test.js +``` + +### Debugging + +In order to run an interactive debugger: + +- `node --inspect-brk node_modules/.bin/jest --runInBand path/to/test/test.js` +- In Chrome, navigate to `chrome://inspect` +- Click `Open dedicated DevTools for Node` +- You'll now be able to interactively debug using the Chrome dev tools. diff --git a/nub/helpers/build b/nub/helpers/build new file mode 100755 index 00000000000..c3cb58c4599 --- /dev/null +++ b/nub/helpers/build @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$DEPENDABOT_NATIVE_HELPERS_PATH" ]; then + echo "Unable to build, DEPENDABOT_NATIVE_HELPERS_PATH is not set" + exit 1 +fi + +install_dir="$DEPENDABOT_NATIVE_HELPERS_PATH/nub" +mkdir -p "$install_dir" + +helpers_dir="$(dirname "${BASH_SOURCE[0]}")" +cp -r \ + "$helpers_dir/lib" \ + "$helpers_dir/test" \ + "$helpers_dir/run.js" \ + "$helpers_dir/.eslintrc" \ + "$helpers_dir/jest.config.js" \ + "$helpers_dir/package.json" \ + "$helpers_dir/package-lock.json" \ + "$helpers_dir/patches" \ + "$install_dir" + +cd "$install_dir" +npm ci --fetch-timeout=600000 --fetch-retries=5 diff --git a/nub/helpers/jest.config.js b/nub/helpers/jest.config.js new file mode 100644 index 00000000000..7e0b1b317ea --- /dev/null +++ b/nub/helpers/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + verbose: true, + rootDir: "test", + testEnvironment: "node", +}; diff --git a/nub/helpers/lib/npm/conflicting-dependency-parser.js b/nub/helpers/lib/npm/conflicting-dependency-parser.js new file mode 100644 index 00000000000..f47c2ac7798 --- /dev/null +++ b/nub/helpers/lib/npm/conflicting-dependency-parser.js @@ -0,0 +1,78 @@ +/* Conflicting dependency parser for npm + * + * Inputs: + * - directory containing a package.json and a yarn.lock + * - dependency name + * - target dependency version + * + * Outputs: + * - An array of objects with conflicting dependencies + */ + +const Arborist = require("@npmcli/arborist"); +const semver = require("semver"); + +async function findConflictingDependencies(directory, depName, targetVersion) { + const arb = new Arborist({ + path: directory, + dryRun: true, + ignoreScripts: true, + }); + + return await arb.loadVirtual().then((tree) => { + const parents = []; + for (const node of tree.inventory.query("name", depName)) { + for (const edge of node.edgesIn) { + if (!semver.satisfies(targetVersion, edge.spec)) { + findTopLevelEdges(edge).forEach((topLevel) => { + explanation = buildExplanation(node, edge, topLevel); + + parents.push({ + explanation: explanation, + name: edge.from.name, + version: edge.from.version, + requirement: edge.spec, + }); + }); + } + } + } + + return parents; + }); +} + +function buildExplanation(node, directEdge, topLevelEdge) { + if (directEdge.from === topLevelEdge.to) { + // The nodes parent is top-level + return `${directEdge.from.name}@${directEdge.from.version} requires ${directEdge.to.name}@${directEdge.spec}`; + } else if (topLevelEdge.to.edgesOut.has(directEdge.from.name)) { + // The nodes parent is a direct dependency of the top-level dependency + return ( + `${topLevelEdge.to.name}@${topLevelEdge.to.version} requires ${directEdge.to.name}@${directEdge.spec} ` + + `via ${directEdge.from.name}@${directEdge.from.version}` + ); + } else { + // The nodes parent is a transitive dependency of the top-level dependency + return ( + `${topLevelEdge.to.name}@${topLevelEdge.to.version} requires ${directEdge.to.name}@${directEdge.spec} ` + + `via a transitive dependency on ${directEdge.from.name}@${directEdge.from.version}` + ); + } +} + +function findTopLevelEdges(edge, parents = []) { + edge.from.edgesIn.forEach((parent) => { + if (parent.from.edgesIn.size === 0) { + if (!parents.includes(parent)) { + parents.push(parent); + } + } else { + findTopLevelEdges(parent, parents); + } + }); + + return parents; +} + +module.exports = { findConflictingDependencies }; diff --git a/nub/helpers/lib/npm/index.js b/nub/helpers/lib/npm/index.js new file mode 100644 index 00000000000..22ba9edee7d --- /dev/null +++ b/nub/helpers/lib/npm/index.js @@ -0,0 +1,9 @@ +const conflictingDependencyParser = require("./conflicting-dependency-parser"); +const vulnerabilityAuditor = require("./vulnerability-auditor"); + +module.exports = { + findConflictingDependencies: + conflictingDependencyParser.findConflictingDependencies, + vulnerabilityAuditor: + vulnerabilityAuditor.findVulnerableDependencies, +}; diff --git a/nub/helpers/lib/npm/vulnerability-auditor.js b/nub/helpers/lib/npm/vulnerability-auditor.js new file mode 100644 index 00000000000..3f82025705e --- /dev/null +++ b/nub/helpers/lib/npm/vulnerability-auditor.js @@ -0,0 +1,291 @@ +/* Vulnerability auditor for npm + * + * Inputs: + * - path to directory containing a package.json and a package-lock.json + * - array of security advisories to audit for, + * [ + * { dependency_name: string, affected_versions: [string, ...] }, + * ... + * ] + * + * Outputs: + * - object indicating whether a fix is available and how to achieve it, + * { + * dependency_name: string, + * current_version: string, + * target_version: string, + * fix_available: boolean | object, + * fix_updates: [ + * { + * dependency_name: string, + * current_version: string, + * target_version: string + * }, + * ... + * ] + * } + */ + +const Arborist = require('@npmcli/arborist') +const nock = require('nock') +const { promisify } = require('util'); +const exec = promisify(require('child_process').exec) + +async function findVulnerableDependencies(directory, advisories) { + const npmConfig = await loadNpmConfig() + const caCerts = loadCACerts(npmConfig) + const registryOpts = extractRegistryOptions(npmConfig) + const registryCreds = loadNpmConfigCredentials(directory) + + const arb = new Arborist({ + path: directory, + auditRegistry: 'http://localhost:9999', + ca: caCerts, + force: true, + dryRun: true, + ignoreScripts: true, + ...registryOpts, + ...registryCreds, + }) + + const scope = nock('http://localhost:9999') + .persist() + .post('/-/npm/v1/security/advisories/bulk') + .reply(200, convertAdvisoriesToRegistryBulkFormat(advisories)) + + if (!nock.isActive()) { + nock.activate() + } + + try { + const name = advisories[0].dependency_name + const response = { + dependency_name: name, + fix_updates: [], + top_level_ancestors: [], + } + const auditReport = await arb.audit() + if (!auditReport.has(name)) { + if (auditReport.tree.children.has(name)) { + response.current_version = auditReport.tree.children.get(name).version + } + response.fix_available = false + return response + } + const vuln = auditReport.get(name) + const version = [...vuln.nodes][0].version + const fixAvailable = vuln.fixAvailable + + response.current_version = version + response.fix_available = Boolean(fixAvailable) + + if (!Boolean(fixAvailable)) { + return response + } + + const chains = buildDependencyChains(auditReport, name) + + // In order for the vuln dependency in question to be considered fixable, + // all dependency chains originating from it must be fixable. + if (chains.some((chain) => !Boolean(chain.fixAvailable))) { + response.fix_available = false + return response + } + + const groupedFixUpdateChains = groupBy(chains, (chain) => chain.nodes[0].pkgid) + let topLevelAncestors = new Set() + + for (const group of groupedFixUpdateChains.values()) { + const fixUpdateNode = group[0].nodes[0] + const groupTopLevelAncestors = group.reduce((ancestor, chain) => { + const topLevelNode = chain.nodes[chain.nodes.length - 1] + return ancestor.add(topLevelNode.name) + }, new Set()) + + // Add group's top-level ancestors to the set of all top-level ancestors of + // the vuln dependency in question. + topLevelAncestors = new Set([...topLevelAncestors, ...groupTopLevelAncestors]) + + // If a chain consists of only one node, chain.nodes[0].name == chain.nodes[chain.nodes.length-1].name. + // In such cases, don't include the fix update node as an ancestor of itself. + const fixUpdateNodeTopLevelAncestors = + [...groupTopLevelAncestors].filter((nodeName) => nodeName !== fixUpdateNode.name).sort() + + response.fix_updates.push({ + dependency_name: fixUpdateNode.name, + current_version: fixUpdateNode.version, + top_level_ancestors: fixUpdateNodeTopLevelAncestors, + }) + } + + response.top_level_ancestors = [...topLevelAncestors].sort() + + const fixTree = await arb.audit({ + fix: true, + }) + + response.target_version = fixTree.children.get(name)?.version + + for (const update of response.fix_updates) { + update.target_version = + fixTree.children.get(update.dependency_name)?.version + } + + return response + } finally { + nock.cleanAll() + nock.restore() + } +} + +function convertAdvisoriesToRegistryBulkFormat(advisories) { + return advisories.reduce((formattedAdvisories, advisory) => { + if (!formattedAdvisories[advisory.dependency_name]) { + formattedAdvisories[advisory.dependency_name] = [] + } + let formattedVersions = + advisory.affected_versions.reduce((memo, version) => { + memo.push({ + id: Math.floor(Math.random() * Number.MAX_SAFE_INTEGER), + vulnerable_versions: version + }) + return memo + }, []) + formattedAdvisories[advisory.dependency_name].push(...formattedVersions) + return formattedAdvisories + }, {}) +} + +/* Returns an array of dependency chains rooted in the named dependency, + * [ + * { + * fixAvailable: true | false | object, + * nodes: [ + * ArboristNode { + * name: 'foo', + * version: '1.0.0', + * ... + * }, + * ... + * ] + * }, + * ... + * ] + * + * The first node in each chain is the innermost dependency affected by the vuln; + * the `fixAvailable` field applies to this dependency. The last node in each + * chain is always a top-level dependency. + */ +function buildDependencyChains(auditReport, name) { + const helper = (node, chain, visited) => { + if (!node) { + return [] + } + if (visited.has(node.name)) { + // We've already seen this node; end path. + return [] + } + if (auditReport.has(node.name)) { + const vuln = auditReport.get(node.name) + if (vuln.isVulnerable(node)) { + return [{ fixAvailable: vuln.fixAvailable, nodes: [node, ...chain.nodes] }] + } else if (node.name == name) { + // This is a non-vulnerable version of the advisory dependency; end path. + return [] + } + } + if (!node.edgesOut.size) { + // This is a leaf node that is unaffected by the vuln; end path. + return [] + } + return [...node.edgesOut.values()].reduce((chains, { to }) => { + // Only prepend current node to chain/visited if it's not the project root. + const newChain = node.isProjectRoot ? chain : { nodes: [node, ...chain.nodes] } + const newVisited = node.isProjectRoot ? visited : new Set([node.name, ...visited]) + return chains.concat(helper(to, newChain, newVisited)) + }, []) + } + return helper(auditReport.tree, { nodes: [] }, new Set()) +} + +function groupBy(elems, fn) { + const groups = new Map() + for (const [index, elem] of [...elems].entries()) { + const key = fn(elem, index, elems) + groups.set(key, (groups.get(key) || []).concat([elem])) + } + return groups +} + +async function loadNpmConfig() { + const configOutput = await exec('npm config ls --json') + return JSON.parse(configOutput.stdout) +} + +function extractRegistryOptions(npmConfig) { + const opts = [] + for (const [key, value] of Object.entries(npmConfig)) { + if (key == "registry" || key.endsWith(":registry")) { + opts.push([key, value]) + } + } + return Object.fromEntries(opts) +} + +// loadNpmConfig doesn't return registry credentials so we need to manually extract them. If available, +// Dependabot will have written them to the project's .npmrc file. +const ini = require('ini') +const path = require('path') + +const credKeys = ['token', '_authToken', '_auth'] + +function loadNpmConfigCredentials(projectDir) { + const projectNpmrc = maybeReadFile(path.join(projectDir, '.npmrc')) + if (!projectNpmrc) { + return {} + } + + const credentials = [] + const config = ini.parse(projectNpmrc) + for (const [key, value] of Object.entries(config)) { + if (credKeys.includes(key) || credKeys.some((credKey) => key.endsWith(':' + credKey))) { + credentials.push([key, value]) + } + } + return Object.fromEntries(credentials) +} + +// sourced from npm's cli/lib/utils/config/definitions.js for reading certs from the cafile option +const fs = require('fs') +const maybeReadFile = file => { + try { + return fs.readFileSync(file, 'utf8') + } catch (er) { + if (er.code !== 'ENOENT') { + throw er + } + return null + } +} + +function loadCACerts(npmConfig) { + if (npmConfig.ca) { + return npmConfig.ca + } + + if (!npmConfig.cafile) { + return + } + + const raw = maybeReadFile(npmConfig.cafile) + if (!raw) { + return + } + + const delim = '-----END CERTIFICATE-----' + return raw.replace(/\r\n/g, '\n').split(delim) + .filter(section => section.trim()) + .map(section => section.trimStart() + delim) +} + +module.exports = { findVulnerableDependencies } diff --git a/nub/helpers/lib/pnpm/index.js b/nub/helpers/lib/pnpm/index.js new file mode 100644 index 00000000000..a7ec50e3ed8 --- /dev/null +++ b/nub/helpers/lib/pnpm/index.js @@ -0,0 +1,5 @@ +const lockfileParser = require("./lockfile-parser"); + +module.exports = { + parseLockfile: lockfileParser.parse, +}; diff --git a/nub/helpers/lib/pnpm/lockfile-parser.js b/nub/helpers/lib/pnpm/lockfile-parser.js new file mode 100644 index 00000000000..75b97fe0eff --- /dev/null +++ b/nub/helpers/lib/pnpm/lockfile-parser.js @@ -0,0 +1,82 @@ +/* PNPM-LOCK.YAML PARSER + * + * Inputs: + * - directory containing a pnpm-lock.yaml file + * + * Outputs: + * - JSON formatted information of dependencies (name, version, dependency-type) + */ +const { readWantedLockfile } = require("@pnpm/lockfile-file"); +const dependencyPath = require("@pnpm/dependency-path"); + +async function parse(directory) { + const lockfile = await readWantedLockfile(directory, { + ignoreIncompatible: true + }); + + return Object.entries(lockfile.packages ?? {}) + .filter(([depPath, pkgSnapshot]) => { + let dp = dependencyPath.parse(depPath); + return dp && dp.name // null or undefined checked for dependency path (dp) and empty name dps are filtered. + }) + .map(([depPath, pkgSnapshot]) => nameVerDevFromPkgSnapshot(depPath, pkgSnapshot, Object.values(lockfile.importers))) +} + +function nameVerDevFromPkgSnapshot(depPath, pkgSnapshot, projectSnapshots) { + let name; + let version; + + if (!pkgSnapshot.name) { + const pkgInfo = dependencyPath.parse(depPath); + name = pkgInfo.name; + version = pkgInfo.version; + } else { + name = pkgSnapshot.name; + version = pkgSnapshot.version; + } + + let specifiers = []; + let aliased = false; + + projectSnapshots.every(projectSnapshot => { + const projectSpecifiers = projectSnapshot.specifiers; + + if (Object.values(projectSpecifiers).some(specifier => specifier.startsWith(`npm:${name}@`) || specifier == `npm:${name}`)) { + aliased = true; + return false; + } + + currentSpecifier = projectSpecifiers[name]; + + if (!currentSpecifier) { + return true; + } + + let specifierVersion = currentSpecifier.version; + + if (!currentSpecifier.version) { + specifierVersion = projectSnapshot.dependencies?.[name] || projectSnapshot.devDependencies?.[name] || projectSnapshot.optionalDependencies?.[name] + } + + if ( + specifierVersion == version || + specifierVersion.startsWith(`${version}_`) || // lockfileVersion 5.4 + specifierVersion.startsWith(`${version}(`) // lockfileVersion 6.0 + ) { + specifiers.push(currentSpecifier.specifier || currentSpecifier); + } + + return true; + }); + + return { + name: name, + version: version, + resolved: pkgSnapshot.resolution?.tarball, + dev: pkgSnapshot.dev, + specifiers: specifiers, + aliased: aliased + } +} + +module.exports = { parse }; diff --git a/nub/helpers/package-lock.json b/nub/helpers/package-lock.json new file mode 100644 index 00000000000..7e3918c3a90 --- /dev/null +++ b/nub/helpers/package-lock.json @@ -0,0 +1,15176 @@ +{ + "name": "@dependabot/helper", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@dependabot/helper", + "hasInstallScript": true, + "dependencies": { + "@npmcli/arborist": "^9.4.0", + "@pnpm/dependency-path": "^5.1.1", + "@pnpm/lockfile-file": "^9.1.2", + "nock": "^13.5.6", + "patch-package": "^8.0.0", + "semver": "^7.6.3" + }, + "bin": { + "helper": "run.js" + }, + "devDependencies": { + "eslint": "^9.16.0", + "eslint-config-prettier": "^9.1.0", + "jest": "^29.7.0", + "prettier": "^3.4.2" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/js": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==", + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@npmcli/agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", + "integrity": "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==", + "license": "ISC", + "dependencies": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^11.2.1", + "socks-proxy-agent": "^8.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/arborist": { + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.9.1.tgz", + "integrity": "sha512-K0mr16xJ/yiTApeGIFbpgZSvJFOvxO2VJnCBhP543t9NTlHzgL+ewpG0kaWv9xkjeESAlRWHG9Q4lbT/LqHbWw==", + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^5.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/metavuln-calculator": "^9.0.2", + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/query": "^5.0.0", + "@npmcli/redact": "^4.0.0", + "@npmcli/run-script": "^10.0.0", + "bin-links": "^6.0.0", + "cacache": "^20.0.1", + "common-ancestor-path": "^2.0.0", + "hosted-git-info": "^9.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^11.2.1", + "minimatch": "^10.0.3", + "nopt": "^9.0.0", + "npm-install-checks": "^8.0.0", + "npm-package-arg": "^13.0.0", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "pacote": "^21.0.2", + "parse-conflict-json": "^5.0.1", + "proc-log": "^6.0.0", + "proggy": "^4.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "semver": "^7.3.7", + "ssri": "^13.0.0", + "treeverse": "^3.0.0", + "walk-up-path": "^4.0.0" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/arborist/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/fs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", + "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "ini": "^6.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", + "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "license": "ISC", + "dependencies": { + "npm-bundled": "^5.0.0", + "npm-normalize-package-bin": "^5.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/map-workspaces": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-5.0.3.tgz", + "integrity": "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw==", + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "glob": "^13.0.0", + "minimatch": "^10.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/metavuln-calculator": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-9.0.3.tgz", + "integrity": "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg==", + "license": "ISC", + "dependencies": { + "cacache": "^20.0.0", + "json-parse-even-better-errors": "^5.0.0", + "pacote": "^21.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/metavuln-calculator/node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-4.0.0.tgz", + "integrity": "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", + "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", + "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", + "license": "ISC", + "dependencies": { + "@npmcli/git": "^7.0.0", + "glob": "^13.0.0", + "hosted-git-info": "^9.0.0", + "json-parse-even-better-errors": "^5.0.0", + "proc-log": "^6.0.0", + "semver": "^7.5.3", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/package-json/node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "license": "ISC", + "dependencies": { + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-5.0.0.tgz", + "integrity": "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", + "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "node-gyp": "^12.1.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pnpm/constants": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/constants/-/constants-8.0.0.tgz", + "integrity": "sha512-yQosGUvYPpAjb1jOFcdbwekRjZRVxN6C0hHzfRCZrMKbxGjt/E0g0RcFlEDNVZ95tm4oMMcr7nEPa7H7LX3emw==", + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/core-loggers": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/core-loggers/-/core-loggers-10.0.3.tgz", + "integrity": "sha512-G038bkMTuvmgG3XtuajnfoBS/u2CoeywRzJZb3qxvcj1XpLFTDAhHyUv/2Rr+yh6KDOVAuTWqdk+WNfeNf6yrw==", + "dependencies": { + "@pnpm/types": "11.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + }, + "peerDependencies": { + "@pnpm/logger": "^5.0.0" + } + }, + "node_modules/@pnpm/crypto.base32-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-3.0.0.tgz", + "integrity": "sha512-iGKP6rRKng5Tcad1+S+j3UoY5wVZN+z0ZgemlGp69jNgn6EaM4N0Q3mvnDNJ7UZFmL2ClXZZYLNuCk9pUYV3Xg==", + "dependencies": { + "rfc4648": "^1.5.3" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/dependency-path": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/dependency-path/-/dependency-path-5.1.2.tgz", + "integrity": "sha512-223YCb6SiCi2+112wHPiG+fWsnSpGINNYZKVwlNwZugheSRuda68SjpUbjc7JIkmceRUD8gbBguk8ynv8IS4TA==", + "dependencies": { + "@pnpm/crypto.base32-hash": "3.0.0", + "@pnpm/types": "11.0.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/error": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@pnpm/error/-/error-6.0.1.tgz", + "integrity": "sha512-7yjO0RgmWYb4OKgcWC33yD4Z2CxE7Tm7vXX1SmS7GDifDT/bgZZhHeS2xq/+W6y9yhwIrRSA+7AlQL1NM2wIvw==", + "dependencies": { + "@pnpm/constants": "8.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/fetch": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/fetch/-/fetch-8.0.3.tgz", + "integrity": "sha512-yUeoVCc/pPicpdU3s+2Vzl7VfLWDUblizRbglQaaXhAawLWOAYu5a/jMoIclN2dJzh5juRPhYowMX82oTG9Y0Q==", + "dependencies": { + "@pnpm/core-loggers": "10.0.3", + "@pnpm/fetching-types": "6.0.0", + "@pnpm/network.agent": "^2.0.0", + "@pnpm/types": "11.0.0", + "@zkochan/retry": "^0.2.0", + "node-fetch": "npm:@pnpm/node-fetch@1.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + }, + "peerDependencies": { + "@pnpm/logger": "^5.0.0" + } + }, + "node_modules/@pnpm/fetching-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/fetching-types/-/fetching-types-6.0.0.tgz", + "integrity": "sha512-fnsaegb+0q7Ku6AyCmoVtBeCuO8ytB7YMEaGHC+0MGoRsxxa6EVLgi2H4abKr8LLslf5tHJBnOH24DjST3UNfQ==", + "dependencies": { + "@zkochan/retry": "^0.2.0", + "node-fetch": "npm:@pnpm/node-fetch@1.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/git-resolver": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@pnpm/git-resolver/-/git-resolver-9.0.4.tgz", + "integrity": "sha512-k6jglET3h66oLwqoUBslfRWmL6ULXXIHjQoc1uLS0it+m1cI5toHWkrKJOwbI/9K3KQ88EhhulFP4tQQpS+1fg==", + "dependencies": { + "@pnpm/fetch": "8.0.3", + "@pnpm/resolver-base": "13.0.0", + "graceful-git": "^4.0.0", + "hosted-git-info": "npm:@pnpm/hosted-git-info@1.0.0", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/git-resolver/node_modules/hosted-git-info": { + "name": "@pnpm/hosted-git-info", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/hosted-git-info/-/hosted-git-info-1.0.0.tgz", + "integrity": "sha512-QzmNiLShTnNyeTHr+cykG5hYjwph0+v49KHV36Dh8uA2rRMWw30qoZMARuxd00SYdoTwT8bIouqqmzi6TWfJHQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pnpm/git-resolver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pnpm/git-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/git-utils/-/git-utils-2.0.0.tgz", + "integrity": "sha512-k1rv4Zvno/5zJAqE/Mh9V0ehlm14NsYwpXTdaGMtyhkoHvlSckRfr23OIOIM7Q/TRX+LhqyJ2kep50SY2TsZ+g==", + "dependencies": { + "execa": "npm:safe-execa@0.1.2" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/git-utils/node_modules/execa": { + "name": "safe-execa", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/safe-execa/-/safe-execa-0.1.2.tgz", + "integrity": "sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==", + "dependencies": { + "@zkochan/which": "^2.0.3", + "execa": "^5.1.1", + "path-name": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pnpm/git-utils/node_modules/execa/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@pnpm/lockfile-file": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-file/-/lockfile-file-9.1.2.tgz", + "integrity": "sha512-kQxQOTCTt8edqj1EOGzoGO+ef8iZCKN5GHY+KdZ54Mt8LThXVIu9LYTEuNXpaRdu9kH1wpfla5TbUDK0vMEvwg==", + "dependencies": { + "@pnpm/constants": "8.0.0", + "@pnpm/dependency-path": "5.1.2", + "@pnpm/error": "6.0.1", + "@pnpm/git-resolver": "9.0.4", + "@pnpm/git-utils": "2.0.0", + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/lockfile-utils": "11.0.3", + "@pnpm/merge-lockfile-changes": "6.0.4", + "@pnpm/types": "11.0.0", + "@pnpm/util.lex-comparator": "3.0.0", + "@zkochan/rimraf": "^3.0.2", + "comver-to-semver": "^1.0.0", + "js-yaml": "npm:@zkochan/js-yaml@0.0.7", + "normalize-path": "^3.0.0", + "ramda": "npm:@pnpm/ramda@0.28.1", + "semver": "^7.6.2", + "sort-keys": "^4.2.0", + "strip-bom": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + }, + "peerDependencies": { + "@pnpm/logger": "^5.0.0" + } + }, + "node_modules/@pnpm/lockfile-file/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@pnpm/lockfile-file/node_modules/js-yaml": { + "name": "@zkochan/js-yaml", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@pnpm/lockfile-file/node_modules/sort-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", + "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", + "dependencies": { + "is-plain-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pnpm/lockfile-file/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@pnpm/lockfile-types": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-types/-/lockfile-types-7.1.2.tgz", + "integrity": "sha512-+64KoK8gtTS5lxslW8ATtwwEbikW4e9i/OV5eaR+X+//5SeUA796uCN96sKu6q6OzpZi3/aVU4VgVe15MT9XKA==", + "dependencies": { + "@pnpm/types": "11.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/lockfile-utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-utils/-/lockfile-utils-11.0.3.tgz", + "integrity": "sha512-HQ3TjUd7TCRovi6wSJ8wcSe1BxXJVs3Hf1msHSZ3Ng1Bwd8rj2mQBNu022u3279Oe1kz35APN0yYciynWWlWkA==", + "dependencies": { + "@pnpm/dependency-path": "5.1.2", + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/pick-fetcher": "3.0.0", + "@pnpm/resolver-base": "13.0.0", + "@pnpm/types": "11.0.0", + "get-npm-tarball-url": "^2.1.0", + "ramda": "npm:@pnpm/ramda@0.28.1" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/logger": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/logger/-/logger-5.0.0.tgz", + "integrity": "sha512-YfcB2QrX+Wx1o6LD1G2Y2fhDhOix/bAY/oAnMpHoNLsKkWIRbt1oKLkIFvxBMzLwAEPqnYWguJrYC+J6i4ywbw==", + "peer": true, + "dependencies": { + "bole": "^5.0.0", + "ndjson": "^2.0.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/@pnpm/merge-lockfile-changes": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@pnpm/merge-lockfile-changes/-/merge-lockfile-changes-6.0.4.tgz", + "integrity": "sha512-S15nSd/LPZKLArnMfHpQLgK7MvNYvSs9meb839Eh29pqp2wSPHLKOroK4Upbod6SOrGtihmgjmpLaFNAYschpg==", + "dependencies": { + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/types": "11.0.0", + "comver-to-semver": "^1.0.0", + "ramda": "npm:@pnpm/ramda@0.28.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/network.agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.agent/-/network.agent-2.0.0.tgz", + "integrity": "sha512-CqONDs5W6vaAdgQEHyFSr4vj25Pv8eVzwI+oUvId/FBHOcTCgHndLIJGON39JnyQS40+yT9kpEj21la3rcJK2w==", + "dependencies": { + "@pnpm/network.config": "2.0.0", + "@pnpm/network.proxy-agent": "2.0.0", + "agentkeepalive": "4.2.1", + "lru-cache": "7.10.1" + }, + "engines": { + "node": ">=18.12" + } + }, + "node_modules/@pnpm/network.agent/node_modules/lru-cache": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", + "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@pnpm/network.config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.config/-/network.config-2.0.0.tgz", + "integrity": "sha512-DpTQTz4KBUgR0NNo/+/WXFlE4dy4+vgINhR9Eb+qo/Kb9RzGbhTN0ypv3sRYa6YG4UO5ft47rvEtHJ9i6VBwzA==", + "dependencies": { + "nerf-dart": "^1.0.0" + }, + "engines": { + "node": ">=18.12" + } + }, + "node_modules/@pnpm/network.proxy-agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.proxy-agent/-/network.proxy-agent-2.0.0.tgz", + "integrity": "sha512-gCShibUggQS1vveAzr84PhDvwoChR4HrHHdvTB8CqXHQu12eoXO8R01awalZWERrHL3fDkUQcqLqCospm2O/QQ==", + "dependencies": { + "@pnpm/error": "^6.0.0", + "http-proxy-agent": "5.0.0", + "https-proxy-agent": "5.0.1", + "lru-cache": "7.10.1", + "socks-proxy-agent": "6.1.1" + }, + "engines": { + "node": ">=18.12" + } + }, + "node_modules/@pnpm/network.proxy-agent/node_modules/lru-cache": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", + "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==", + "engines": { + "node": ">=12" + } + }, + "node_modules/@pnpm/pick-fetcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/pick-fetcher/-/pick-fetcher-3.0.0.tgz", + "integrity": "sha512-2eisylRAU/jeuxFEPnS1gjLZKJGbYc4QEtEW6MVUYjO4Xi+2ttkSm7825S0J5IPpUIvln8HYPCUS0eQWSfpOaQ==", + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/resolver-base": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/resolver-base/-/resolver-base-13.0.0.tgz", + "integrity": "sha512-hUAn2OqHEBB3MRLlbvtczI0KdNM9CJgd0hDRuLDrcaVrhZrhHDwgLywls+hWbgNvUpcdMR7k+uEIo+07Vu/Qvg==", + "dependencies": { + "@pnpm/types": "11.0.0" + }, + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/types": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/types/-/types-11.0.0.tgz", + "integrity": "sha512-BSdk9nlYLHHHLrTFNpmdrXrXVc+1sY/E1Fs1zqR8pY/KjpjVhxkruLZuXitPRPxbk4jSqm7UnG5WCz008iiaig==", + "engines": { + "node": ">=18.12" + }, + "funding": { + "url": "https://opencollective.com/pnpm" + } + }, + "node_modules/@pnpm/util.lex-comparator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/util.lex-comparator/-/util.lex-comparator-3.0.0.tgz", + "integrity": "sha512-ead+l3IiuVXwKDf/QJPX6G93cwhXki3yOVEA/VdAO7AhZ5vUuSBxHe6gQKEbB0QacJ4H5VsYxeM1xUgwjjOO/Q==", + "engines": { + "node": ">=18.12" + } + }, + "node_modules/@sigstore/bundle": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", + "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.1.tgz", + "integrity": "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==", + "license": "Apache-2.0", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.2.tgz", + "integrity": "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw==", + "license": "Apache-2.0", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", + "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", + "license": "Apache-2.0", + "dependencies": { + "@gar/promise-retry": "^1.0.2", + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.0", + "@sigstore/protobuf-specs": "^0.5.0", + "make-fetch-happen": "^15.0.4", + "proc-log": "^6.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", + "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/protobuf-specs": "^0.5.0", + "tuf-js": "^4.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.1.tgz", + "integrity": "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.1", + "@sigstore/protobuf-specs": "^0.5.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", + "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", + "license": "MIT", + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^10.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.8.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", + "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.28", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", + "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, + "node_modules/@zkochan/retry": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@zkochan/retry/-/retry-0.2.0.tgz", + "integrity": "sha512-WhB+2B/ZPlW2Xy/kMJBrMbqecWXcbDDgn0K0wKBAgO2OlBTz1iLJrRWduo+DGGn0Akvz1Lu4Xvls7dJojximWw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@zkochan/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-GBf4ua7ogWTr7fATnzk/JLowZDBnBJMm8RkMaC/KcvxZ9gxbMWix0/jImd815LmqKyIHZ7h7lADRddGMdGBuCA==", + "engines": { + "node": ">=18.12" + } + }, + "node_modules/@zkochan/which": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@zkochan/which/-/which-2.0.3.tgz", + "integrity": "sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/agentkeepalive/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agentkeepalive/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "node_modules/bin-links": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.2.tgz", + "integrity": "sha512-frE1t78WOwJ45PKV2cF2tNPjTcs9L1J9s6VkrV59wanRP4GlaomuxYPVma7BwthMg8WnfSory4w5PTE6FZZ81w==", + "license": "ISC", + "dependencies": { + "cmd-shim": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "proc-log": "^6.0.0", + "read-cmd-shim": "^6.0.0", + "write-file-atomic": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/bin-links/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/bin-links/node_modules/write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "license": "ISC", + "dependencies": { + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/bole": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/bole/-/bole-5.0.13.tgz", + "integrity": "sha512-JQ3xWh2nYsVUuJx7ZN4fzU3vHpzceWb7CC06LUXWwdY++Hzd7Wola7zN3Ud5XgmOVoH/6KzrdMmJokol/xtejw==", + "peer": true, + "dependencies": { + "fast-safe-stringify": "^2.0.7", + "individual": "^3.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/cacache": { + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.4.tgz", + "integrity": "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==", + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^5.0.0", + "fs-minipass": "^3.0.0", + "glob": "^13.0.0", + "lru-cache": "^11.1.0", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001546", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", + "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cmd-shim": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz", + "integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } + }, + "node_modules/comver-to-semver": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/comver-to-semver/-/comver-to-semver-1.0.0.tgz", + "integrity": "sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "node_modules/content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/create-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/create-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.544", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz", + "integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.5", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "license": "Apache-2.0" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "peer": true + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fetch-blob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", + "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==", + "engines": { + "node": "^10.17.0 || >=12.3.0" + }, + "peerDependenciesMeta": { + "domexception": { + "optional": true + } + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "deprecated": "This module is no longer supported.", + "license": "ISC" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dependencies": { + "micromatch": "^4.0.2" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-npm-tarball-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", + "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/graceful-git": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/graceful-git/-/graceful-git-4.0.0.tgz", + "integrity": "sha512-zK/rCH/I0DMKpPBLCElXGI7za3EnXeQFdiK6CTP02Tt1N1L+bMLghZY7cXozlx9M2bx4Q0zrY9ADYP3eI8haIw==", + "dependencies": { + "retry": "^0.13.1", + "safe-execa": "^0.1.1" + }, + "engines": { + "node": ">=18.12" + } + }, + "node_modules/graceful-git/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "license": "ISC", + "dependencies": { + "lru-cache": "^11.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", + "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", + "license": "ISC", + "dependencies": { + "minimatch": "^10.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/individual": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/individual/-/individual-3.0.0.tgz", + "integrity": "sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==", + "peer": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "peer": true + }, + "node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/ip-address": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "dependencies": { + "jsonify": "^0.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-nice": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/just-diff": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==", + "license": "MIT" + }, + "node_modules/just-diff-apply": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==", + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-fetch-happen": { + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz", + "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==", + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-fetch": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", + "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^2.0.0", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + }, + "optionalDependencies": { + "iconv-lite": "^0.7.2" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", + "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", + "license": "ISC", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "license": "MIT", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "ndjson": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ndjson/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ndjson/node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "license": "MIT", + "dependencies": { + "content-type": "^2.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==" + }, + "node_modules/nock": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", + "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/nock/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nock/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/node-fetch": { + "name": "@pnpm/node-fetch", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/node-fetch/-/node-fetch-1.0.0.tgz", + "integrity": "sha512-eYwrzhKUBGFdq78rJStGjaHTUHA2VH+Avr//CVx/T+EJkI7hnFmOy6YghvcB2clj8HpO4V8tXRNuFNfRX08ayw==", + "dependencies": { + "data-uri-to-buffer": "^3.0.1", + "fetch-blob": "^2.1.1" + }, + "engines": { + "node": "^10.17 || >=12.3" + } + }, + "node_modules/node-gyp": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==", + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "license": "ISC", + "dependencies": { + "abbrev": "^4.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", + "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^5.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-package-arg": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", + "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", + "license": "ISC", + "dependencies": { + "hosted-git-info": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^7.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-packlist": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", + "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", + "license": "ISC", + "dependencies": { + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", + "license": "ISC", + "dependencies": { + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", + "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", + "license": "ISC", + "dependencies": { + "@npmcli/redact": "^4.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.7.tgz", + "integrity": "sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/pacote": { + "version": "21.5.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.1.tgz", + "integrity": "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg==", + "license": "ISC", + "dependencies": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/git": "^7.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^6.0.0", + "sigstore": "^4.0.0", + "ssri": "^13.0.0", + "tar": "^7.4.3" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-conflict-json": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-5.0.1.tgz", + "integrity": "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ==", + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^5.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/parse-conflict-json/node_modules/json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==", + "license": "MIT", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.0.33", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/patch-package/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/patch-package/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/patch-package/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-name/-/path-name-1.0.0.tgz", + "integrity": "sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==" + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/proggy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-4.0.0.tgz", + "integrity": "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/promise-all-reject-late": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-3.0.1.tgz", + "integrity": "sha512-utl+0x8gIDasV5X+PI5qWEPqH6fJS0pFtQ/4gZ95xfEFb/89dmh+/b895TbFDBLiafBvxD/PGTKfvxl4kH/pQg==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/ramda": { + "name": "@pnpm/ramda", + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@pnpm/ramda/-/ramda-0.28.1.tgz", + "integrity": "sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ramda" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-cmd-shim": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz", + "integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "peer": true + }, + "node_modules/safe-execa": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/safe-execa/-/safe-execa-0.1.4.tgz", + "integrity": "sha512-GI3k4zl4aLC3lxZNEEXAxxcXE6E3TfOsJ5xxJPhcAv9MWwnH2O9I0HrDmZFsVnu/C8wzRYSsTHdoVRmL0VicDw==", + "dependencies": { + "@zkochan/which": "^2.0.3", + "execa": "^5.1.1", + "path-name": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT", + "optional": true + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/sigstore": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz", + "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==", + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.2.1", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "license": "CC0-1.0" + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "license": "ISC", + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "peer": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/treeverse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", + "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", + "license": "MIT", + "dependencies": { + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", + "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "dev": true, + "requires": { + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", + "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "dev": true + }, + "@babel/core": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-compilation-targets": "^7.22.15", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "dev": true, + "requires": { + "@babel/types": "^7.23.0", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", + "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.15", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", + "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.15" + } + }, + "@babel/helper-module-transforms": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", + "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "dev": true + }, + "@babel/helpers": { + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" + } + }, + "@babel/highlight": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/template": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" + } + }, + "@babel/traverse": { + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true + }, + "@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + } + } + }, + "@eslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.15" + } + }, + "@eslint/eslintrc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "4.3.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "requires": { + "ms": "^2.1.3" + } + } + } + }, + "@eslint/js": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", + "dev": true + }, + "@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true + }, + "@eslint/plugin-kit": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "dev": true, + "requires": { + "levn": "^0.4.1" + } + }, + "@gar/promise-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@gar/promise-retry/-/promise-retry-1.0.3.tgz", + "integrity": "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA==" + }, + "@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true + }, + "@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "requires": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "dependencies": { + "@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true + } + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "requires": { + "ansi-regex": "5.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "requires": { + "minipass": "^7.0.4" + } + }, + "@isaacs/string-locale-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz", + "integrity": "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==" + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "4.3.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "4.0.8", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + } + }, + "@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } + }, + "@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3" + } + }, + "@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } + }, + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "10.5.0", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "4.0.8", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + } + } + }, + "@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@npmcli/agent": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-4.0.2.tgz", + "integrity": "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==", + "requires": { + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^11.2.1", + "socks-proxy-agent": "^8.0.3" + }, + "dependencies": { + "agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==" + }, + "http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "requires": { + "agent-base": "^7.1.2", + "debug": "4" + } + }, + "lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + }, + "socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "requires": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + } + } + } + }, + "@npmcli/arborist": { + "version": "9.9.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-9.9.1.tgz", + "integrity": "sha512-K0mr16xJ/yiTApeGIFbpgZSvJFOvxO2VJnCBhP543t9NTlHzgL+ewpG0kaWv9xkjeESAlRWHG9Q4lbT/LqHbWw==", + "requires": { + "@gar/promise-retry": "^1.0.0", + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^5.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/map-workspaces": "^5.0.0", + "@npmcli/metavuln-calculator": "^9.0.2", + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/query": "^5.0.0", + "@npmcli/redact": "^4.0.0", + "@npmcli/run-script": "^10.0.0", + "bin-links": "^6.0.0", + "cacache": "^20.0.1", + "common-ancestor-path": "^2.0.0", + "hosted-git-info": "^9.0.0", + "json-stringify-nice": "^1.1.4", + "lru-cache": "^11.2.1", + "minimatch": "^10.0.3", + "nopt": "^9.0.0", + "npm-install-checks": "^8.0.0", + "npm-package-arg": "^13.0.0", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "pacote": "^21.0.2", + "parse-conflict-json": "^5.0.1", + "proc-log": "^6.0.0", + "proggy": "^4.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^3.0.1", + "semver": "^7.3.7", + "ssri": "6.0.2", + "treeverse": "^3.0.0", + "walk-up-path": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + }, + "minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "requires": { + "brace-expansion": "1.1.18" + } + } + } + }, + "@npmcli/fs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-5.0.0.tgz", + "integrity": "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==", + "requires": { + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-7.0.2.tgz", + "integrity": "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==", + "requires": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "ini": "^6.0.0", + "lru-cache": "^11.2.1", + "npm-pick-manifest": "^11.0.1", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "which": "^6.0.0" + }, + "dependencies": { + "isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==" + }, + "lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + }, + "which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "requires": { + "isexe": "^4.0.0" + } + } + } + }, + "@npmcli/installed-package-contents": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", + "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "requires": { + "npm-bundled": "^5.0.0", + "npm-normalize-package-bin": "^5.0.0" + } + }, + "@npmcli/map-workspaces": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-5.0.3.tgz", + "integrity": "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw==", + "requires": { + "@npmcli/name-from-folder": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "glob": "10.5.0", + "minimatch": "^10.0.3" + }, + "dependencies": { + "minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "requires": { + "brace-expansion": "1.1.18" + } + } + } + }, + "@npmcli/metavuln-calculator": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-9.0.3.tgz", + "integrity": "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg==", + "requires": { + "cacache": "^20.0.0", + "json-parse-even-better-errors": "^5.0.0", + "pacote": "^21.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==" + } + } + }, + "@npmcli/name-from-folder": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-4.0.0.tgz", + "integrity": "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg==" + }, + "@npmcli/node-gyp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-5.0.0.tgz", + "integrity": "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ==" + }, + "@npmcli/package-json": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-7.0.5.tgz", + "integrity": "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ==", + "requires": { + "@npmcli/git": "^7.0.0", + "glob": "10.5.0", + "hosted-git-info": "^9.0.0", + "json-parse-even-better-errors": "^5.0.0", + "proc-log": "^6.0.0", + "semver": "^7.5.3", + "spdx-expression-parse": "^4.0.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==" + } + } + }, + "@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "requires": { + "which": "^6.0.0" + }, + "dependencies": { + "isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==" + }, + "which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "requires": { + "isexe": "^4.0.0" + } + } + } + }, + "@npmcli/query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/query/-/query-5.0.0.tgz", + "integrity": "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ==", + "requires": { + "postcss-selector-parser": "^7.0.0" + } + }, + "@npmcli/redact": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-4.0.0.tgz", + "integrity": "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==" + }, + "@npmcli/run-script": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-10.0.4.tgz", + "integrity": "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==", + "requires": { + "@npmcli/node-gyp": "^5.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "node-gyp": "^12.1.0", + "proc-log": "^6.0.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true + }, + "@pnpm/constants": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/constants/-/constants-8.0.0.tgz", + "integrity": "sha512-yQosGUvYPpAjb1jOFcdbwekRjZRVxN6C0hHzfRCZrMKbxGjt/E0g0RcFlEDNVZ95tm4oMMcr7nEPa7H7LX3emw==" + }, + "@pnpm/core-loggers": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/core-loggers/-/core-loggers-10.0.3.tgz", + "integrity": "sha512-G038bkMTuvmgG3XtuajnfoBS/u2CoeywRzJZb3qxvcj1XpLFTDAhHyUv/2Rr+yh6KDOVAuTWqdk+WNfeNf6yrw==", + "requires": { + "@pnpm/types": "11.0.0" + } + }, + "@pnpm/crypto.base32-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/crypto.base32-hash/-/crypto.base32-hash-3.0.0.tgz", + "integrity": "sha512-iGKP6rRKng5Tcad1+S+j3UoY5wVZN+z0ZgemlGp69jNgn6EaM4N0Q3mvnDNJ7UZFmL2ClXZZYLNuCk9pUYV3Xg==", + "requires": { + "rfc4648": "^1.5.3" + } + }, + "@pnpm/dependency-path": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/dependency-path/-/dependency-path-5.1.2.tgz", + "integrity": "sha512-223YCb6SiCi2+112wHPiG+fWsnSpGINNYZKVwlNwZugheSRuda68SjpUbjc7JIkmceRUD8gbBguk8ynv8IS4TA==", + "requires": { + "@pnpm/crypto.base32-hash": "3.0.0", + "@pnpm/types": "11.0.0", + "semver": "^7.6.2" + } + }, + "@pnpm/error": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@pnpm/error/-/error-6.0.1.tgz", + "integrity": "sha512-7yjO0RgmWYb4OKgcWC33yD4Z2CxE7Tm7vXX1SmS7GDifDT/bgZZhHeS2xq/+W6y9yhwIrRSA+7AlQL1NM2wIvw==", + "requires": { + "@pnpm/constants": "8.0.0" + } + }, + "@pnpm/fetch": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/fetch/-/fetch-8.0.3.tgz", + "integrity": "sha512-yUeoVCc/pPicpdU3s+2Vzl7VfLWDUblizRbglQaaXhAawLWOAYu5a/jMoIclN2dJzh5juRPhYowMX82oTG9Y0Q==", + "requires": { + "@pnpm/core-loggers": "10.0.3", + "@pnpm/fetching-types": "6.0.0", + "@pnpm/network.agent": "^2.0.0", + "@pnpm/types": "11.0.0", + "@zkochan/retry": "^0.2.0", + "node-fetch": "npm:@pnpm/node-fetch@1.0.0" + } + }, + "@pnpm/fetching-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/fetching-types/-/fetching-types-6.0.0.tgz", + "integrity": "sha512-fnsaegb+0q7Ku6AyCmoVtBeCuO8ytB7YMEaGHC+0MGoRsxxa6EVLgi2H4abKr8LLslf5tHJBnOH24DjST3UNfQ==", + "requires": { + "@zkochan/retry": "^0.2.0", + "node-fetch": "npm:@pnpm/node-fetch@1.0.0" + } + }, + "@pnpm/git-resolver": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@pnpm/git-resolver/-/git-resolver-9.0.4.tgz", + "integrity": "sha512-k6jglET3h66oLwqoUBslfRWmL6ULXXIHjQoc1uLS0it+m1cI5toHWkrKJOwbI/9K3KQ88EhhulFP4tQQpS+1fg==", + "requires": { + "@pnpm/fetch": "8.0.3", + "@pnpm/resolver-base": "13.0.0", + "graceful-git": "^4.0.0", + "hosted-git-info": "npm:@pnpm/hosted-git-info@1.0.0", + "semver": "^7.6.2" + }, + "dependencies": { + "hosted-git-info": { + "version": "npm:@pnpm/hosted-git-info@1.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/hosted-git-info/-/hosted-git-info-1.0.0.tgz", + "integrity": "sha512-QzmNiLShTnNyeTHr+cykG5hYjwph0+v49KHV36Dh8uA2rRMWw30qoZMARuxd00SYdoTwT8bIouqqmzi6TWfJHQ==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "@pnpm/git-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/git-utils/-/git-utils-2.0.0.tgz", + "integrity": "sha512-k1rv4Zvno/5zJAqE/Mh9V0ehlm14NsYwpXTdaGMtyhkoHvlSckRfr23OIOIM7Q/TRX+LhqyJ2kep50SY2TsZ+g==", + "requires": { + "execa": "npm:safe-execa@0.1.2" + }, + "dependencies": { + "execa": { + "version": "npm:safe-execa@0.1.2", + "resolved": "https://registry.npmjs.org/safe-execa/-/safe-execa-0.1.2.tgz", + "integrity": "sha512-vdTshSQ2JsRCgT8eKZWNJIL26C6bVqy1SOmuCMlKHegVeo8KYRobRrefOdUq9OozSPUUiSxrylteeRmLOMFfWg==", + "requires": { + "@zkochan/which": "^2.0.3", + "execa": "^5.1.1", + "path-name": "^1.0.0" + }, + "dependencies": { + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + } + } + } + } + }, + "@pnpm/lockfile-file": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-file/-/lockfile-file-9.1.2.tgz", + "integrity": "sha512-kQxQOTCTt8edqj1EOGzoGO+ef8iZCKN5GHY+KdZ54Mt8LThXVIu9LYTEuNXpaRdu9kH1wpfla5TbUDK0vMEvwg==", + "requires": { + "@pnpm/constants": "8.0.0", + "@pnpm/dependency-path": "5.1.2", + "@pnpm/error": "6.0.1", + "@pnpm/git-resolver": "9.0.4", + "@pnpm/git-utils": "2.0.0", + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/lockfile-utils": "11.0.3", + "@pnpm/merge-lockfile-changes": "6.0.4", + "@pnpm/types": "11.0.0", + "@pnpm/util.lex-comparator": "3.0.0", + "@zkochan/rimraf": "^3.0.2", + "comver-to-semver": "^1.0.0", + "js-yaml": "4.3.1", + "normalize-path": "^3.0.0", + "ramda": "npm:@pnpm/ramda@0.28.1", + "semver": "^7.6.2", + "sort-keys": "^4.2.0", + "strip-bom": "^4.0.0", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + }, + "js-yaml": { + "version": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", + "integrity": "sha512-nrUSn7hzt7J6JWgWGz78ZYI8wj+gdIJdk0Ynjpp8l+trkn58Uqsf6RYrYkEK+3X18EX+TNdtJI0WxAtc+L84SQ==", + "requires": { + "argparse": "^2.0.1" + } + }, + "sort-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-4.2.0.tgz", + "integrity": "sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==", + "requires": { + "is-plain-obj": "^2.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + } + } + }, + "@pnpm/lockfile-types": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-types/-/lockfile-types-7.1.2.tgz", + "integrity": "sha512-+64KoK8gtTS5lxslW8ATtwwEbikW4e9i/OV5eaR+X+//5SeUA796uCN96sKu6q6OzpZi3/aVU4VgVe15MT9XKA==", + "requires": { + "@pnpm/types": "11.0.0" + } + }, + "@pnpm/lockfile-utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@pnpm/lockfile-utils/-/lockfile-utils-11.0.3.tgz", + "integrity": "sha512-HQ3TjUd7TCRovi6wSJ8wcSe1BxXJVs3Hf1msHSZ3Ng1Bwd8rj2mQBNu022u3279Oe1kz35APN0yYciynWWlWkA==", + "requires": { + "@pnpm/dependency-path": "5.1.2", + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/pick-fetcher": "3.0.0", + "@pnpm/resolver-base": "13.0.0", + "@pnpm/types": "11.0.0", + "get-npm-tarball-url": "^2.1.0", + "ramda": "npm:@pnpm/ramda@0.28.1" + } + }, + "@pnpm/logger": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/logger/-/logger-5.0.0.tgz", + "integrity": "sha512-YfcB2QrX+Wx1o6LD1G2Y2fhDhOix/bAY/oAnMpHoNLsKkWIRbt1oKLkIFvxBMzLwAEPqnYWguJrYC+J6i4ywbw==", + "peer": true, + "requires": { + "bole": "^5.0.0", + "ndjson": "^2.0.0" + } + }, + "@pnpm/merge-lockfile-changes": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@pnpm/merge-lockfile-changes/-/merge-lockfile-changes-6.0.4.tgz", + "integrity": "sha512-S15nSd/LPZKLArnMfHpQLgK7MvNYvSs9meb839Eh29pqp2wSPHLKOroK4Upbod6SOrGtihmgjmpLaFNAYschpg==", + "requires": { + "@pnpm/lockfile-types": "7.1.2", + "@pnpm/types": "11.0.0", + "comver-to-semver": "^1.0.0", + "ramda": "npm:@pnpm/ramda@0.28.1", + "semver": "^7.6.2" + } + }, + "@pnpm/network.agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.agent/-/network.agent-2.0.0.tgz", + "integrity": "sha512-CqONDs5W6vaAdgQEHyFSr4vj25Pv8eVzwI+oUvId/FBHOcTCgHndLIJGON39JnyQS40+yT9kpEj21la3rcJK2w==", + "requires": { + "@pnpm/network.config": "2.0.0", + "@pnpm/network.proxy-agent": "2.0.0", + "agentkeepalive": "4.2.1", + "lru-cache": "7.10.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", + "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==" + } + } + }, + "@pnpm/network.config": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.config/-/network.config-2.0.0.tgz", + "integrity": "sha512-DpTQTz4KBUgR0NNo/+/WXFlE4dy4+vgINhR9Eb+qo/Kb9RzGbhTN0ypv3sRYa6YG4UO5ft47rvEtHJ9i6VBwzA==", + "requires": { + "nerf-dart": "^1.0.0" + } + }, + "@pnpm/network.proxy-agent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/network.proxy-agent/-/network.proxy-agent-2.0.0.tgz", + "integrity": "sha512-gCShibUggQS1vveAzr84PhDvwoChR4HrHHdvTB8CqXHQu12eoXO8R01awalZWERrHL3fDkUQcqLqCospm2O/QQ==", + "requires": { + "@pnpm/error": "^6.0.0", + "http-proxy-agent": "5.0.0", + "https-proxy-agent": "5.0.1", + "lru-cache": "7.10.1", + "socks-proxy-agent": "6.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz", + "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==" + } + } + }, + "@pnpm/pick-fetcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/pick-fetcher/-/pick-fetcher-3.0.0.tgz", + "integrity": "sha512-2eisylRAU/jeuxFEPnS1gjLZKJGbYc4QEtEW6MVUYjO4Xi+2ttkSm7825S0J5IPpUIvln8HYPCUS0eQWSfpOaQ==" + }, + "@pnpm/resolver-base": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/resolver-base/-/resolver-base-13.0.0.tgz", + "integrity": "sha512-hUAn2OqHEBB3MRLlbvtczI0KdNM9CJgd0hDRuLDrcaVrhZrhHDwgLywls+hWbgNvUpcdMR7k+uEIo+07Vu/Qvg==", + "requires": { + "@pnpm/types": "11.0.0" + } + }, + "@pnpm/types": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/types/-/types-11.0.0.tgz", + "integrity": "sha512-BSdk9nlYLHHHLrTFNpmdrXrXVc+1sY/E1Fs1zqR8pY/KjpjVhxkruLZuXitPRPxbk4jSqm7UnG5WCz008iiaig==" + }, + "@pnpm/util.lex-comparator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/util.lex-comparator/-/util.lex-comparator-3.0.0.tgz", + "integrity": "sha512-ead+l3IiuVXwKDf/QJPX6G93cwhXki3yOVEA/VdAO7AhZ5vUuSBxHe6gQKEbB0QacJ4H5VsYxeM1xUgwjjOO/Q==" + }, + "@sigstore/bundle": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-4.0.0.tgz", + "integrity": "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==", + "requires": { + "@sigstore/protobuf-specs": "^0.5.0" + } + }, + "@sigstore/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-3.2.1.tgz", + "integrity": "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==" + }, + "@sigstore/protobuf-specs": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.5.2.tgz", + "integrity": "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw==" + }, + "@sigstore/sign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-4.1.1.tgz", + "integrity": "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==", + "requires": { + "@gar/promise-retry": "^1.0.2", + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "3.2.1", + "@sigstore/protobuf-specs": "^0.5.0", + "make-fetch-happen": "^15.0.4", + "proc-log": "^6.1.0" + } + }, + "@sigstore/tuf": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.2.tgz", + "integrity": "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==", + "requires": { + "@sigstore/protobuf-specs": "^0.5.0", + "tuf-js": "^4.1.0" + } + }, + "@sigstore/verify": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-3.1.1.tgz", + "integrity": "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==", + "requires": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "3.2.1", + "@sigstore/protobuf-specs": "^0.5.0" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==" + }, + "@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==" + }, + "@tufjs/models": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-4.1.0.tgz", + "integrity": "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww==", + "requires": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^10.1.1" + }, + "dependencies": { + "minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "requires": { + "brace-expansion": "1.1.18" + } + } + } + }, + "@types/babel__core": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", + "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.5", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", + "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", + "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", + "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "@types/graceful-fs": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", + "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "@types/node": { + "version": "20.8.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", + "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.28", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.28.tgz", + "integrity": "sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==" + }, + "@zkochan/retry": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@zkochan/retry/-/retry-0.2.0.tgz", + "integrity": "sha512-WhB+2B/ZPlW2Xy/kMJBrMbqecWXcbDDgn0K0wKBAgO2OlBTz1iLJrRWduo+DGGn0Akvz1Lu4Xvls7dJojximWw==" + }, + "@zkochan/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@zkochan/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-GBf4ua7ogWTr7fATnzk/JLowZDBnBJMm8RkMaC/KcvxZ9gxbMWix0/jImd815LmqKyIHZ7h7lADRddGMdGBuCA==" + }, + "@zkochan/which": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@zkochan/which/-/which-2.0.3.tgz", + "integrity": "sha512-C1ReN7vt2/2O0fyTsx5xnbQuxBrmG5NMSbcIkPKCCfCTJgpZBsuRYzFXHj3nVq8vTfK7vxHUmzfCpSHgO7j4rg==", + "requires": { + "isexe": "^2.0.0" + } + }, + "abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==" + }, + "acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "dependencies": { + "debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "2.3.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bin-links": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-6.0.2.tgz", + "integrity": "sha512-frE1t78WOwJ45PKV2cF2tNPjTcs9L1J9s6VkrV59wanRP4GlaomuxYPVma7BwthMg8WnfSory4w5PTE6FZZ81w==", + "requires": { + "cmd-shim": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "proc-log": "^6.0.0", + "read-cmd-shim": "^6.0.0", + "write-file-atomic": "^7.0.0" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + }, + "write-file-atomic": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-7.0.1.tgz", + "integrity": "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg==", + "requires": { + "signal-exit": "^4.0.1" + } + } + } + }, + "bole": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/bole/-/bole-5.0.13.tgz", + "integrity": "sha512-JQ3xWh2nYsVUuJx7ZN4fzU3vHpzceWb7CC06LUXWwdY++Hzd7Wola7zN3Ud5XgmOVoH/6KzrdMmJokol/xtejw==", + "peer": true, + "requires": { + "fast-safe-stringify": "^2.0.7", + "individual": "^3.0.0" + } + }, + "brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "requires": { + "fill-range": "^7.1.1" + } + }, + "browserslist": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.13" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "cacache": { + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-20.0.4.tgz", + "integrity": "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==", + "requires": { + "@npmcli/fs": "^5.0.0", + "fs-minipass": "^3.0.0", + "glob": "10.5.0", + "lru-cache": "^11.1.0", + "minipass": "^7.0.3", + "minipass-collect": "^2.0.1", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^7.0.2", + "ssri": "6.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001546", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", + "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "cmd-shim": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-8.0.0.tgz", + "integrity": "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "common-ancestor-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==" + }, + "comver-to-semver": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/comver-to-semver/-/comver-to-semver-1.0.0.tgz", + "integrity": "sha512-gcGtbRxjwROQOdXLUWH1fQAXqThUVRZ219aAwgtX3KfYw429/Zv6EIJRf5TBSzWdAGwePmqH7w70WTaX4MDqag==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "content-type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz", + "integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==" + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==" + }, + "debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "requires": { + "ms": "^2.1.3" + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "electron-to-chromium": { + "version": "1.4.544", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz", + "integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==", + "dev": true + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.5", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "requires": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true + } + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "peer": true + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "requires": {} + }, + "fetch-blob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz", + "integrity": "sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow==" + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" + }, + "file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "requires": { + "flat-cache": "^4.0.0" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "requires": { + "micromatch": "4.0.8" + } + }, + "flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + } + }, + "flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true + }, + "foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "requires": { + "minipass": "^7.0.3" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-npm-tarball-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz", + "integrity": "sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "dependencies": { + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "requires": { + "brace-expansion": "1.1.18" + } + } + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "graceful-git": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/graceful-git/-/graceful-git-4.0.0.tgz", + "integrity": "sha512-zK/rCH/I0DMKpPBLCElXGI7za3EnXeQFdiK6CTP02Tt1N1L+bMLghZY7cXozlx9M2bx4Q0zrY9ADYP3eI8haIw==", + "requires": { + "retry": "^0.13.1", + "safe-execa": "^0.1.1" + }, + "dependencies": { + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "hosted-git-info": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.3.tgz", + "integrity": "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==", + "requires": { + "lru-cache": "^11.1.0" + }, + "dependencies": { + "lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==" + } + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "requires": { + "@tootallnate/once": "2.0.1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true + }, + "ignore-walk": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-8.0.0.tgz", + "integrity": "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A==", + "requires": { + "minimatch": "^10.0.3" + }, + "dependencies": { + "minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "requires": { + "brace-expansion": "1.1.18" + } + } + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "individual": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/individual/-/individual-3.0.0.tgz", + "integrity": "sha512-rUY5vtT748NMRbEMrTNiFfy29BgGZwGXUi2NFUVMWQrogSLzlJvQV9eeMWi+g1aVaQ53tpyLAQtd5x/JH0Nh1g==", + "peer": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "peer": true + }, + "ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==" + }, + "ip-address": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "10.5.0", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "4.0.8", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "4.0.8", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "10.5.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "2.3.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "requires": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", + "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", + "requires": { + "jsonify": "^0.0.1" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-nice": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.4.tgz", + "integrity": "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==" + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==" + }, + "just-diff": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-6.0.2.tgz", + "integrity": "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA==" + }, + "just-diff-apply": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-5.5.0.tgz", + "integrity": "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw==" + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "requires": { + "graceful-fs": "^4.1.11" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "make-fetch-happen": { + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.6.tgz", + "integrity": "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==", + "requires": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/agent": "^4.0.0", + "@npmcli/redact": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", + "ssri": "6.0.2" + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "requires": { + "braces": "3.0.3", + "picomatch": "2.3.2" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "requires": { + "brace-expansion": "1.1.18" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==" + }, + "minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "requires": { + "minipass": "^7.0.3" + } + }, + "minipass-fetch": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-5.0.2.tgz", + "integrity": "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==", + "requires": { + "iconv-lite": "^0.7.2", + "minipass": "^7.0.3", + "minipass-sized": "^2.0.0", + "minizlib": "^3.0.1" + } + }, + "minipass-flush": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", + "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-sized": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-2.0.0.tgz", + "integrity": "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA==", + "requires": { + "minipass": "^7.1.2" + } + }, + "minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "requires": { + "minipass": "^7.1.2" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "peer": true, + "requires": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "peer": true, + "requires": { + "readable-stream": "3" + } + } + } + }, + "negotiator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz", + "integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==", + "requires": { + "content-type": "^2.1.0" + } + }, + "nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==" + }, + "nock": { + "version": "13.5.6", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", + "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", + "requires": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "propagate": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "node-fetch": { + "version": "npm:@pnpm/node-fetch@1.0.0", + "resolved": "https://registry.npmjs.org/@pnpm/node-fetch/-/node-fetch-1.0.0.tgz", + "integrity": "sha512-eYwrzhKUBGFdq78rJStGjaHTUHA2VH+Avr//CVx/T+EJkI7hnFmOy6YghvcB2clj8HpO4V8tXRNuFNfRX08ayw==", + "requires": { + "data-uri-to-buffer": "^3.0.1", + "fetch-blob": "^2.1.1" + } + }, + "node-gyp": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==", + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "7.5.22", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" + }, + "dependencies": { + "isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==" + }, + "which": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", + "requires": { + "isexe": "^4.0.0" + } + } + } + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "dev": true + }, + "nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "requires": { + "abbrev": "^4.0.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-bundled": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", + "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", + "requires": { + "npm-normalize-package-bin": "^5.0.0" + } + }, + "npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==" + }, + "npm-package-arg": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", + "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", + "requires": { + "hosted-git-info": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^7.0.0" + } + }, + "npm-packlist": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.4.tgz", + "integrity": "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==", + "requires": { + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" + } + }, + "npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", + "requires": { + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" + } + }, + "npm-registry-fetch": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", + "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", + "requires": { + "@npmcli/redact": "^4.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^6.0.0" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-map": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.7.tgz", + "integrity": "sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ==" + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "pacote": { + "version": "21.5.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.5.1.tgz", + "integrity": "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg==", + "requires": { + "@gar/promise-retry": "^1.0.0", + "@npmcli/git": "^7.0.0", + "@npmcli/installed-package-contents": "^4.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^9.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^6.0.0", + "sigstore": "4.1.1", + "ssri": "6.0.2", + "tar": "7.5.22" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-conflict-json": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-5.0.1.tgz", + "integrity": "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ==", + "requires": { + "json-parse-even-better-errors": "^5.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-5.0.0.tgz", + "integrity": "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ==" + } + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "patch-package": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.0.tgz", + "integrity": "sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==", + "requires": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^9.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "rimraf": "^2.6.3", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "0.2.7", + "yaml": "2.8.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "10.5.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-name": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-name/-/path-name-1.0.0.tgz", + "integrity": "sha512-/dcAb5vMXH0f51yvMuSUqFpxUcA8JelbRmE5mW/p4CUJxrNgK24IkstnV7ENtg2IDGBOu6izKTG6eilbnbNKWQ==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==" + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "postcss-selector-parser": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.5.tgz", + "integrity": "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", + "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "dev": true + }, + "pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==" + }, + "proggy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/proggy/-/proggy-4.0.0.tgz", + "integrity": "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ==" + }, + "promise-all-reject-late": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==" + }, + "promise-call-limit": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-3.0.1.tgz", + "integrity": "sha512-utl+0x8gIDasV5X+PI5qWEPqH6fJS0pFtQ/4gZ95xfEFb/89dmh+/b895TbFDBLiafBvxD/PGTKfvxl4kH/pQg==" + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "pure-rand": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", + "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true + }, + "ramda": { + "version": "npm:@pnpm/ramda@0.28.1", + "resolved": "https://registry.npmjs.org/@pnpm/ramda/-/ramda-0.28.1.tgz", + "integrity": "sha512-zcAG+lvU0fMziNeGXpPyCyCJYp5ZVrPElEE4t14jAmViaihohocZ+dDkcRIyAomox8pQsuZnv1EyHR+pOhmUWw==" + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "read-cmd-shim": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-6.0.0.tgz", + "integrity": "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A==" + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "rfc4648": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.3.tgz", + "integrity": "sha512-MjOWxM065+WswwnmNONOT+bD1nXzY9Km6u3kzvnx8F8/HXGZdz3T6e6vZJ8Q/RIMUSp/nxqjH3GwvJDy8ijeQQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "peer": true + }, + "safe-execa": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/safe-execa/-/safe-execa-0.1.4.tgz", + "integrity": "sha512-GI3k4zl4aLC3lxZNEEXAxxcXE6E3TfOsJ5xxJPhcAv9MWwnH2O9I0HrDmZFsVnu/C8wzRYSsTHdoVRmL0VicDw==", + "requires": { + "@zkochan/which": "^2.0.3", + "execa": "^5.1.1", + "path-name": "^1.0.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "sigstore": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.1.tgz", + "integrity": "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==", + "requires": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "3.2.1", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.1.1", + "@sigstore/tuf": "^4.0.2", + "@sigstore/verify": "^3.1.1" + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "requires": { + "ip-address": "10.4.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==" + }, + "spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==" + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "peer": true, + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "peer": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "5.0.1" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "7.5.22", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz", + "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==", + "requires": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "dependencies": { + "yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "10.5.0", + "minimatch": "^3.0.4" + } + }, + "tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "requires": { + "fdir": "^6.5.0", + "picomatch": "2.3.2" + } + }, + "tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==" + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "treeverse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-3.0.0.tgz", + "integrity": "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ==" + }, + "tuf-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", + "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", + "requires": { + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "undici": { + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz", + "integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "v8-to-istanbul": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", + "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, + "validate-npm-package-name": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", + "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==" + }, + "walk-up-path": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-4.0.0.tgz", + "integrity": "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==" + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==" + } + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==" + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "5.0.1" + } + } + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/nub/helpers/package.json b/nub/helpers/package.json new file mode 100644 index 00000000000..052f59eec75 --- /dev/null +++ b/nub/helpers/package.json @@ -0,0 +1,47 @@ +{ + "name": "@dependabot/helper", + "private": true, + "bin": { + "helper": "run.js" + }, + "scripts": { + "lint": "eslint .", + "test": "jest", + "postinstall": "patch-package" + }, + "dependencies": { + "@npmcli/arborist": "^9.4.0", + "nock": "^13.5.6", + "@pnpm/lockfile-file": "^9.1.2", + "@pnpm/dependency-path": "^5.1.1", + "semver": "^7.6.3", + "patch-package": "^8.0.0" + }, + "devDependencies": { + "eslint": "^9.16.0", + "eslint-config-prettier": "^9.1.0", + "jest": "^29.7.0", + "prettier": "^3.4.2" + }, + "overrides": { + "form-data": "2.5.6", + "@sigstore/core": "3.2.1", + "@tootallnate/once": "2.0.1", + "ansi-regex": "5.0.1", + "brace-expansion": "1.1.18", + "braces": "3.0.3", + "glob": "10.5.0", + "ip-address": "10.4.0", + "lodash": "4.18.0", + "micromatch": "4.0.8", + "picomatch": "2.3.2", + "qs": "6.15.3", + "sigstore": "4.1.1", + "ssri": "6.0.2", + "tar": "7.5.22", + "tmp": "0.2.7", + "tough-cookie": "4.1.3", + "yaml": "2.8.3", + "js-yaml": "4.3.1" + } +} diff --git a/nub/helpers/patches/.gitkeep b/nub/helpers/patches/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/nub/helpers/run.js b/nub/helpers/run.js new file mode 100644 index 00000000000..662182ebebe --- /dev/null +++ b/nub/helpers/run.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +const process = require('process'); + +function output(obj) { + process.stdout.write(JSON.stringify(obj)); +} + +const input = []; +process.stdin.on("data", (data) => input.push(data)); +process.stdin.on("end", () => { + const request = JSON.parse(input.join("")); + const [manager, functionName] = request.function.split(":"); + const helpers = require(`./lib/${manager}`); + const func = helpers[functionName]; + if (!func) { + output({ error: `Invalid function ${request.function}` }); + process.exit(1); + } + + func + .apply(null, request.args) + .then((result) => { + output({ result: result }); + }) + .catch((error) => { + output({ error: error.message }); + process.exit(1); + }); +}); diff --git a/nub/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml b/nub/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml new file mode 100644 index 00000000000..6e210ee4382 --- /dev/null +++ b/nub/helpers/test/pnpm/fixtures/parser/empty_version/pnpm-lock.yaml @@ -0,0 +1,72 @@ +lockfileVersion: 5.4 + +specifiers: + etag: 1.7.0 + fetch-factory: ^0.0.1 + +dependencies: + fetch-factory: + specifier: ^0.0.1 + version: 0.0.1 + +devDependencies: + etag: + specifier: 1.7.0 + version: 1.7.0 + +packages: + + /encoding/: + resolution: {integrity: sha512-bl1LAgiQc4ZWr++pNYUdRe/alecaHFeHxIJ/pNciqGdKXghaTCOwKkbKp6ye7pKZGu/GcaSXFk8PBVhgs+dJdA==} + dependencies: + iconv-lite: 0.4.15 + dev: false + + /es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: false + + /etag@1.7.0: + resolution: {integrity: sha512-Mbv5pNpLNPrm1b4rzZlZlfTRpdDr31oiD43N362sIyvSWVNu5Du33EcJGzvEV4YdYLuENB1HzND907cQkFmXNw==} + engines: {node: '>= 0.6'} + dev: true + + /fetch-factory@0.0.1: + resolution: {integrity: sha512-gexRwqIhwzDJ2pJvL0UYfiZwW06/bdYWxAmswFFts7C87CF8i6liApihTk7TZFYMDcQjvvDIvyHv0q379z0aWA==} + dependencies: + es6-promise: 3.3.1 + isomorphic-fetch: 2.2.1 + lodash: 3.10.1 + dev: false + + /iconv-lite@0.4.15: + resolution: {integrity: sha512-RGR+c9Lm+tLsvU57FTJJtdbv2hQw42Yl2n26tVIBaYmZzLN+EGfroUugN/z9nJf9kOXd49hBmpoGr4FEm+A4pw==} + engines: {node: '>=0.10.0'} + dev: false + + /is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + dev: false + + /isomorphic-fetch@2.2.1: + resolution: {integrity: sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==} + dependencies: + node-fetch: 1.7.3 + whatwg-fetch: 3.6.2 + dev: false + + /lodash@3.10.1: + resolution: {integrity: sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==} + dev: false + + /node-fetch@1.7.3: + resolution: {integrity: sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==} + dependencies: + encoding: 0.1.12 + is-stream: 1.1.0 + dev: false + + /whatwg-fetch@3.6.2: + resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} + dev: false diff --git a/nub/helpers/test/pnpm/fixtures/parser/lockfile_v9/pnpm-lock.yaml b/nub/helpers/test/pnpm/fixtures/parser/lockfile_v9/pnpm-lock.yaml new file mode 100644 index 00000000000..5516ebd2744 --- /dev/null +++ b/nub/helpers/test/pnpm/fixtures/parser/lockfile_v9/pnpm-lock.yaml @@ -0,0 +1,23 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + etag: + specifier: ^1.0.0 + version: 1.8.1 + +packages: + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + +snapshots: + + etag@1.8.1: {} diff --git a/nub/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml b/nub/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml new file mode 100644 index 00000000000..a8cafc5aa8f --- /dev/null +++ b/nub/helpers/test/pnpm/fixtures/parser/no_lockfile_change/pnpm-lock.yaml @@ -0,0 +1,2744 @@ +lockfileVersion: '6.0' + +dependencies: + fetch-factory: + specifier: ^0.0.1 + version: 0.0.1 + +devDependencies: + babel-core: + specifier: ^6.26.0 + version: 6.26.0 + babel-register: + specifier: ^6.24.1 + version: 6.24.1 + jest: + specifier: 22.0.4 + version: 22.0.4 + +packages: + + /@babel/code-frame@7.0.0-beta.35: + resolution: {integrity: sha512-l0SE8cl9DUIY4hYAFAKTLX3F2Yr14Qri7uTsuI7iegB5E4KyQy4XY72L3VOxmj6kwR/RDQURoKYr2NzyETGo7A==} + dependencies: + chalk: 2.0.1 + esutils: 2.0.2 + js-tokens: 3.0.2 + dev: true + + /@types/node@8.5.2: + resolution: {integrity: sha512-KA4GKOpgXnrqEH2eCVhiv2CsxgXGQJgV1X0vsGlh+WCnxbeAE1GT44ZsTU1IN5dEeV/gDupKa7gWo08V5IxWVQ==} + dev: true + + /abab@1.0.3: + resolution: {integrity: sha512-Nr2I36rULSLYUzwP7ssOYfvNKy38ud5CAUZCyPIYNArPdJkVzk0wI8VkB6vLsHSFZXoOM+Bp94iMNrdhGU+ZMw==} + dev: true + + /acorn-globals@4.1.0: + resolution: {integrity: sha512-KjZwU26uG3u6eZcfGbTULzFcsoz6pegNKtHPksZPOUsiKo5bUmiBPa38FuHZ/Eun+XYh/JCCkS9AS3Lu4McQOQ==} + dependencies: + acorn: 5.2.1 + dev: true + + /acorn@5.2.1: + resolution: {integrity: sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@5.5.2: + resolution: {integrity: sha512-Ajr4IcMXq/2QmMkEmSvxqfLN5zGmJ92gHXAeOXq1OekoH2rfDNsgdDoL2f7QaRCy7G/E6TpxBVdRuNraMztGHw==} + dependencies: + co: 4.6.0 + fast-deep-equal: 1.0.0 + fast-json-stable-stringify: 2.0.0 + json-schema-traverse: 0.3.1 + dev: true + + /align-text@0.1.4: + resolution: {integrity: sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: true + optional: true + + /amdefine@1.0.1: + resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} + engines: {node: '>=0.4.2'} + dev: true + + /ansi-escapes@3.0.0: + resolution: {integrity: sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==} + engines: {node: '>=4'} + dev: true + + /ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-regex@3.0.0: + resolution: {integrity: sha512-wFUFA5bg5dviipbQQ32yOQhl6gcJaJXiHE7dvR8VYPG97+J/GNC5FKGepKdEDUFeXRzDxPF1X/Btc8L+v7oqIQ==} + engines: {node: '>=4'} + dev: true + + /ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + dev: true + + /ansi-styles@3.2.0: + resolution: {integrity: sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.0 + dev: true + + /anymatch@1.3.2: + resolution: {integrity: sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==} + dependencies: + micromatch: 2.3.11 + normalize-path: 2.1.1 + dev: true + + /append-transform@0.4.0: + resolution: {integrity: sha512-Yisb7ew0ZEyDtRYQ+b+26o9KbiYPFxwcsxKzbssigzRRMJ9LpExPVUg6Fos7eP7yP3q7///tzze4nm4lTptPBw==} + engines: {node: '>=0.10.0'} + dependencies: + default-require-extensions: 1.0.0 + dev: true + + /argparse@1.0.9: + resolution: {integrity: sha512-iK7YPKV+GsvihPUTKcM3hh2gq47zSFCpVDv/Ay2O9mzuD7dfvLV4vhms4XcjZvv4VRgXuGLMEts51IlTjS11/A==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /arr-diff@2.0.0: + resolution: {integrity: sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-flatten: 1.1.0 + dev: true + + /arr-flatten@1.1.0: + resolution: {integrity: sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==} + engines: {node: '>=0.10.0'} + dev: true + + /array-equal@1.0.0: + resolution: {integrity: sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==} + dev: true + + /array-unique@0.2.1: + resolution: {integrity: sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==} + engines: {node: '>=0.10.0'} + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /asn1@0.2.3: + resolution: {integrity: sha512-6i37w/+EhlWlGUJff3T/Q8u1RGmP5wgbiwYnOnbOqvtrPxT63/sYFyP9RcpxtxGymtfA075IvmOnL7ycNOWl3w==} + dev: true + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: true + + /astral-regex@1.0.0: + resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} + engines: {node: '>=4'} + dev: true + + /async@1.5.2: + resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} + dev: true + + /async@2.5.0: + resolution: {integrity: sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==} + dependencies: + lodash: 4.17.4 + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: true + + /aws4@1.6.0: + resolution: {integrity: sha512-tkleq4Df8UWu/7xf/tfbo7t2vDa07bcONGnKhl0QXKQsh3fJ0yJ1M5wzpy8BtBSENQw/9VTsthMhLG+yXHfStQ==} + dev: true + + /babel-code-frame@6.26.0: + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} + dependencies: + chalk: 1.1.3 + esutils: 2.0.2 + js-tokens: 3.0.2 + dev: true + + /babel-core@6.26.0: + resolution: {integrity: sha512-FSiqfr4SYrH5Zv5KgWahyY99VC+Aod1ioMRNvL1lPS4WTUqvPAdYo7ioWEhDHEDqZADapbJZMX0sBuRsc93bDQ==} + dependencies: + babel-code-frame: 6.26.0 + babel-generator: 6.26.0 + babel-helpers: 6.24.1 + babel-messages: 6.23.0 + babel-register: 6.26.0 + babel-runtime: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + convert-source-map: 1.5.1 + debug: 2.6.8 + json5: 0.5.1 + lodash: 4.17.4 + minimatch: 3.0.4 + path-is-absolute: 1.0.1 + private: 0.1.8 + slash: 1.0.0 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-generator@6.26.0: + resolution: {integrity: sha512-9SxJ4+NI4HBbS3U5wtiY+Fd/XRH8D4WHeeQVwViYijL73U1jXQHjxmn9aOiD+/orbvw7YgakoyO3eejaE3Gk2Q==} + dependencies: + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + detect-indent: 4.0.0 + jsesc: 1.3.0 + lodash: 4.17.4 + source-map: 0.5.7 + trim-right: 1.0.1 + dev: true + + /babel-helpers@6.24.1: + resolution: {integrity: sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==} + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-jest@22.0.4(babel-core@6.26.0): + resolution: {integrity: sha512-/Yt61fUpdFjetYlnpj280BPKEsPnK4mqzxDdo8DybPvrPNrLurbAF/WBjn2nnoi1Hc2Ippsf12/aOp8ys/Vl1A==} + peerDependencies: + babel-core: ^6.0.0 || ^7.0.0-0 + dependencies: + babel-core: 6.26.0 + babel-plugin-istanbul: 4.1.5 + babel-preset-jest: 22.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-messages@6.23.0: + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} + dependencies: + babel-runtime: 6.26.0 + dev: true + + /babel-plugin-istanbul@4.1.5: + resolution: {integrity: sha512-uOxwl1iYngetP9Ci36B5XC29bZfkiXs3bi4NTc5wxhtH365/kFRTBW04chlyx/6heRVTnOfL08JYEiLeKI2oXA==} + dependencies: + find-up: 2.1.0 + istanbul-lib-instrument: 1.9.1 + test-exclude: 4.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@22.0.3: + resolution: {integrity: sha512-Z0pOZFs0xDctwF0bPEKrnAzvbbgDi2vDFbQ0EdofnLI2bOa3P1H66gNLb2vMJJaa00VDjfiGhIocsHvBkqtyEQ==} + dev: true + + /babel-plugin-syntax-object-rest-spread@6.13.0: + resolution: {integrity: sha512-C4Aq+GaAj83pRQ0EFgTvw5YO6T3Qz2KGrNRwIj9mSoNHVvdZY4KO2uA6HNtNXCw993iSZnckY1aLW8nOi8i4+w==} + dev: true + + /babel-preset-jest@22.0.3: + resolution: {integrity: sha512-FbMMniSMXFvkKldCf+e4Tuol/v3XMaIpIp8xiT1WFlEW3ZapTKDW9YgVt3hqcpZXsIGFf6eUF3Owxom7yFlI8w==} + dependencies: + babel-plugin-jest-hoist: 22.0.3 + babel-plugin-syntax-object-rest-spread: 6.13.0 + dev: true + + /babel-register@6.24.1: + resolution: {integrity: sha512-mr00+i4WOTiZoG1+CYfemP6mW9ym7Hw97EtEx60Z0/uTADXXPjVc9D4xXYi96zyCZMBALF7EjC0cVAS+63updw==} + dependencies: + babel-core: 6.26.0 + babel-runtime: 6.26.0 + core-js: 2.5.0 + home-or-tmp: 2.0.0 + lodash: 4.17.4 + mkdirp: 0.5.1 + source-map-support: 0.4.18 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-register@6.26.0: + resolution: {integrity: sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==} + dependencies: + babel-core: 6.26.0 + babel-runtime: 6.26.0 + core-js: 2.5.0 + home-or-tmp: 2.0.0 + lodash: 4.17.4 + mkdirp: 0.5.1 + source-map-support: 0.4.18 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-runtime@6.26.0: + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} + dependencies: + core-js: 2.5.0 + regenerator-runtime: 0.11.0 + dev: true + + /babel-template@6.26.0: + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} + dependencies: + babel-runtime: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + lodash: 4.17.4 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-traverse@6.26.0: + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} + dependencies: + babel-code-frame: 6.26.0 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + debug: 2.6.8 + globals: 9.18.0 + invariant: 2.2.2 + lodash: 4.17.4 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-types@6.26.0: + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.2 + lodash: 4.17.4 + to-fast-properties: 1.0.3 + dev: true + + /babylon@6.18.0: + resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} + hasBin: true + dev: true + + /balanced-match@1.0.0: + resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} + dev: true + + /bcrypt-pbkdf@1.0.1: + resolution: {integrity: sha512-vY4sOrSlpwNZXsinfJ0HpbSkFft4nhSVLeUrQ4j2ydGmBOiVY83aMJStJATBy0C3+XdaYa990kIA1qkC2mUq6g==} + requiresBuild: true + dependencies: + tweetnacl: 0.14.5 + dev: true + optional: true + + /bindings@1.3.0: + resolution: {integrity: sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==} + dev: true + optional: true + + /boom@4.3.1: + resolution: {integrity: sha512-FA8ZqcHBLjyFCPns8EsFTWxARi8iKzLfl3vXS1n1O6mlUpZvjXg9E+0Ys8mh7k/s8mHVpROgeoUmz4HadhPhAQ==} + engines: {node: '>=4.0.0'} + deprecated: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial). + dependencies: + hoek: 4.2.0 + dev: true + + /boom@5.2.0: + resolution: {integrity: sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==} + engines: {node: '>=4.0.0'} + deprecated: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial). + dependencies: + hoek: 4.2.0 + dev: true + + /brace-expansion@1.1.8: + resolution: {integrity: sha512-Dnfc9ROAPrkkeLIUweEbh7LFT9Mc53tO/bbM044rKjhgAEyIGKvKXg97PM/kRizZIfUHaROZIoeEaWao+Unzfw==} + dependencies: + balanced-match: 1.0.0 + concat-map: 0.0.1 + dev: true + + /braces@1.8.5: + resolution: {integrity: sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==} + engines: {node: '>=0.10.0'} + dependencies: + expand-range: 1.8.2 + preserve: 0.2.0 + repeat-element: 1.1.2 + dev: true + + /browser-process-hrtime@0.1.2: + resolution: {integrity: sha512-Ceq8IlrEQ38T8tlKS6sCYIcOn6qwkFyAnjCcvoqt0mvu25lxTeJXc6NcOmh90ZiNn3zlWXHX+4bPy/vOq8HCDA==} + dev: true + + /browser-resolve@1.11.2: + resolution: {integrity: sha512-IBmTH6PPKm10Mnf/ja+YKXZEyH7pyrxBUbbyr0ZEDBGhNOIWVHo41gTWWU4DhYPKt6JIx2YwTsyrULjTsx7/+A==} + dependencies: + resolve: 1.1.7 + dev: true + + /bser@2.0.0: + resolution: {integrity: sha512-FozP+z0rEpi3AywbeT1QnOrGFJDbC0986aFDR2NlNLF+/WEYdv/7/qb1FVtla+KBWswkQBOA7okWd+85ThWlCQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /builtin-modules@1.1.1: + resolution: {integrity: sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==} + engines: {node: '>=0.10.0'} + dev: true + + /callsites@2.0.0: + resolution: {integrity: sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==} + engines: {node: '>=4'} + dev: true + + /camelcase@1.2.1: + resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} + engines: {node: '>=0.10.0'} + dev: true + optional: true + + /camelcase@4.1.0: + resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} + engines: {node: '>=4'} + dev: true + + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: true + + /center-align@0.1.3: + resolution: {integrity: sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: true + optional: true + + /chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + dev: true + + /chalk@2.0.1: + resolution: {integrity: sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==} + engines: {node: '>=4'} + deprecated: Please upgrade to Chalk 2.1.0 - template literals in this version (2.0.1) are quite buggy. + dependencies: + ansi-styles: 3.2.0 + escape-string-regexp: 1.0.5 + supports-color: 4.2.1 + dev: true + + /ci-info@1.0.0: + resolution: {integrity: sha512-ew7IacPPJ0TskWg2F9XOYpHEyTn/WGYc5PID1k8kGci8/MLuJVVajQ2RrzckPPkORD6eoE9O6IsrUUZc3j6nHQ==} + dev: true + + /cliui@2.1.0: + resolution: {integrity: sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==} + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: true + optional: true + + /cliui@3.2.0: + resolution: {integrity: sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==} + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + wrap-ansi: 2.1.0 + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /code-point-at@1.1.0: + resolution: {integrity: sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==} + engines: {node: '>=0.10.0'} + dev: true + + /color-convert@1.9.0: + resolution: {integrity: sha512-cBdgwBveAUUexnimWkdqoTDizLaNhyWPRTvsNQI7eg2k5Y8sqQzymwc2V0qGhX0QdsPS9pqR5nOxEiMAE7SmHQ==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /combined-stream@1.0.5: + resolution: {integrity: sha512-JgSRe4l4UzPwpJuxfcPWEK1SCrL4dxNjp1uqrQLMop3QZUVo+hDU8w9BJKA4JPbulTWI+UzrI2UA3tK12yQ6bg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /content-type-parser@1.0.1: + resolution: {integrity: sha512-wcQIkUC9peMxKmyzj9LYdHpv14Oav63ffMMXBUcjUiQgcBWJ8z4QI5/R9CWDfy+qEZH8Bvx0d550Aw1to2HU0w==} + dev: true + + /convert-source-map@1.5.1: + resolution: {integrity: sha512-LNHI/Ll1UqBTGhrR6vMhtVZmX4kjYdCJUjIM6Ydp7/oJ5w1C0MKrzELuUAmMlU0eKwBGx6PaO0TRZ/KDXAFTBg==} + dev: true + + /core-js@2.5.0: + resolution: {integrity: sha512-mAPLSnIVZAwVEf8OZtnNcF2BL1d6DHV3EvIWj46UDBYNAqLxx7mLLpQxe8/1vtrkzt1KIyjmOqOG3pa+bZf7Fw==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + dev: true + + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: true + + /cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + dependencies: + lru-cache: 4.1.1 + shebang-command: 1.2.0 + which: 1.3.0 + dev: true + + /cryptiles@3.1.2: + resolution: {integrity: sha512-XBDBQo47RxVcR5GNxNOI38Cac044AdfU60sJBGZsmWw5TDuG5BAby8W/soTp4SIKeCl37sCGwkbh9wGLEd0cLw==} + engines: {node: '>=4.0.0'} + deprecated: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial). + dependencies: + boom: 5.2.0 + dev: true + + /cssom@0.3.2: + resolution: {integrity: sha512-N72oNABuYrOUdPYkT64J8mvYNxFU35kU4Zer3N69aWz4AylPUlSiS/75J+VMAMz9OFf+TTrN3UBrPbcEegOqtg==} + dev: true + + /cssstyle@0.2.37: + resolution: {integrity: sha512-FUpKc+1FNBsHUr9IsfSGCovr8VuGOiiuzlgCyppKBjJi2jYTOFLN3oiiNRMIvYqbFzF38mqKj4BgcevzU5/kIA==} + dependencies: + cssom: 0.3.2 + dev: true + + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: true + + /debug@2.6.8: + resolution: {integrity: sha512-E22fsyWPt/lr4/UgQLt/pXqerGMDsanhbnmqIS3VAXuDi1v3IpiwXe2oncEIondHSBuPDWRoK/pMjlvi8FuOXQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /debug@3.1.0: + resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /deep-is@0.1.3: + resolution: {integrity: sha512-GtxAN4HvBachZzm4OnWqc45ESpUCMwkYcsjnsPs23FwJbsO+k4t0k9bQCgOmzIlpHO28+WPK/KRbRk0DDHuuDw==} + dev: true + + /default-require-extensions@1.0.0: + resolution: {integrity: sha512-Dn2eAftOqXhNXs5f/Xjn7QTZ6kDYkx7u0EXQInN1oyYwsZysu11q7oTtaKcbzLxZRJiDHa8VmwpWmb4lY5FqgA==} + engines: {node: '>=0.10.0'} + dependencies: + strip-bom: 2.0.0 + dev: true + + /define-properties@1.1.2: + resolution: {integrity: sha512-hpr5VSFXGamODSCN6P2zdSBY6zJT7DlcBAHiPIa2PWDvfBqJQntSK0ehUoHoS6HGeSS19dgj7E+1xOjfG3zEtQ==} + engines: {node: '>= 0.4'} + dependencies: + foreach: 2.0.5 + object-keys: 1.0.11 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /detect-indent@4.0.0: + resolution: {integrity: sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==} + engines: {node: '>=0.10.0'} + dependencies: + repeating: 2.0.1 + dev: true + + /detect-newline@2.1.0: + resolution: {integrity: sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==} + engines: {node: '>=0.10.0'} + dev: true + + /diff@3.3.0: + resolution: {integrity: sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==} + engines: {node: '>=0.3.1'} + dev: true + + /domexception@1.0.0: + resolution: {integrity: sha512-WpwuBlZ2lQRFa4H/4w49deb9rJLot9KmqrKKjMc9qBl7CID+DdC2swoa34ccRl+anL2B6bLp6TjFdIdnzekMBQ==} + dev: true + + /ecc-jsbn@0.1.1: + resolution: {integrity: sha512-8Pvg9QY16SYajEL9W1Lk+9yM7XCK/MOq2wibslLZYAAEEkbAIO6mLkW+GFYbvvw8qTuDFzFMg40rS9IxkNCWPg==} + requiresBuild: true + dependencies: + jsbn: 0.1.1 + dev: true + optional: true + + /encoding@0.1.12: + resolution: {integrity: sha512-bl1LAgiQc4ZWr++pNYUdRe/alecaHFeHxIJ/pNciqGdKXghaTCOwKkbKp6ye7pKZGu/GcaSXFk8PBVhgs+dJdA==} + dependencies: + iconv-lite: 0.4.19 + dev: false + + /error-ex@1.3.1: + resolution: {integrity: sha512-FfmVxYsm1QOFoPI2xQmNnEH10Af42mCxtGrKvS1JfDTXlPLYiAz2T+QpjHPxf+OGniMfWZah9ULAhPoKQ3SEqg==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.10.0: + resolution: {integrity: sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==} + engines: {node: '>= 0.4'} + dependencies: + es-to-primitive: 1.1.1 + function-bind: 1.1.1 + has: 1.0.1 + is-callable: 1.1.3 + is-regex: 1.0.4 + dev: true + + /es-to-primitive@1.1.1: + resolution: {integrity: sha512-wXsac552n5sYhgVjyFvhXLunXZFPOiT/WgP7hFhUPU5gtaUQpm9OryPwlWQUS3Qptk8iZzY/2T3J62GtC/toSw==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.1.3 + is-date-object: 1.0.1 + is-symbol: 1.0.1 + dev: true + + /es6-promise@3.3.1: + resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escodegen@1.9.0: + resolution: {integrity: sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==} + engines: {node: '>=0.12.0'} + hasBin: true + dependencies: + esprima: 3.1.3 + estraverse: 4.2.0 + esutils: 2.0.2 + optionator: 0.8.2 + optionalDependencies: + source-map: 0.5.7 + dev: true + + /esprima@3.1.3: + resolution: {integrity: sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esprima@4.0.0: + resolution: {integrity: sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /estraverse@4.2.0: + resolution: {integrity: sha512-VHvyaGnJy+FuGfcfaM7W7OZw4mQiKW73jPHwQXx2VnMSUBajYmytOT5sKEfsBvNPtGX6YDwcrGDz2eocoHg0JA==} + engines: {node: '>=0.10.0'} + dev: true + + /esutils@2.0.2: + resolution: {integrity: sha512-UUPPULqkyAV+M3Shodis7l8D+IyX6V8SbaBnTb449jf3fMTd8+UOZI1Q70NbZVOQkcR91yYgdHsJiMMMVmYshg==} + engines: {node: '>=0.10.0'} + dev: true + + /exec-sh@0.2.0: + resolution: {integrity: sha512-0fYLrl1wA/3waJI7XFzqj1AaJXDiOt/scDFSNsb4mz7BGbwymOdVgb8afAP+AlCxxSzmQrW/YWeUCDvjX/rNXw==} + dependencies: + merge: 1.2.0 + dev: true + + /execa@0.7.0: + resolution: {integrity: sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==} + engines: {node: '>=4'} + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.2 + strip-eof: 1.0.0 + dev: true + + /expand-brackets@0.1.5: + resolution: {integrity: sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==} + engines: {node: '>=0.10.0'} + dependencies: + is-posix-bracket: 0.1.1 + dev: true + + /expand-range@1.8.2: + resolution: {integrity: sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==} + engines: {node: '>=0.10.0'} + dependencies: + fill-range: 2.2.3 + dev: true + + /expect@22.0.3: + resolution: {integrity: sha512-QapzeQkcA3jCx4pDnD07I4SPPxScKbey8TD/WwrnzmpHmL5q0dUtXfUt5OIFOjVBCg+C4zn4Y1zK9Rb9SIDL1g==} + dependencies: + ansi-styles: 3.2.0 + jest-diff: 22.0.3 + jest-get-type: 22.0.3 + jest-matcher-utils: 22.0.3 + jest-message-util: 22.0.3 + jest-regex-util: 22.0.3 + dev: true + + /extend@3.0.1: + resolution: {integrity: sha512-u1aUSYGdAQxyguoP919qsgj24krDCtaO/DJFNPwFmojMmKp14gtCTVsc8lQSqRDFrwAch+mxMWC8/6ZJPz5Hpw==} + dev: true + + /extglob@0.3.2: + resolution: {integrity: sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 1.0.0 + dev: true + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: true + + /fast-deep-equal@1.0.0: + resolution: {integrity: sha512-46+Jxk9Yj/nQY+3a1KTnpbBTemcAbPySTKya8iM9D7EsiONpSWbvzesalcCJ6tmJrCUITT2fmAQfNHFG+OHM6Q==} + dev: true + + /fast-json-stable-stringify@2.0.0: + resolution: {integrity: sha512-eIgZvM9C3P05kg0qxfqaVU6Tma4QedCPIByQOcemV0vju8ot3cS2DpHi4m2G2JvbSMI152rjfLX0p1pkSdyPlQ==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fb-watchman@2.0.0: + resolution: {integrity: sha512-+6dk4acfiWsbMc8pH0boQDeQprOM4mO/kS4IAvZVJZk4B6CZYLg4DkTGbL82vhglUXDtkJPnLfO0WXv3uxGNfA==} + dependencies: + bser: 2.0.0 + dev: true + + /fetch-factory@0.0.1: + resolution: {integrity: sha512-gexRwqIhwzDJ2pJvL0UYfiZwW06/bdYWxAmswFFts7C87CF8i6liApihTk7TZFYMDcQjvvDIvyHv0q379z0aWA==} + dependencies: + es6-promise: 3.3.1 + isomorphic-fetch: 2.2.1 + dev: false + + /filename-regex@2.0.1: + resolution: {integrity: sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==} + engines: {node: '>=0.10.0'} + dev: true + + /fileset@2.0.3: + resolution: {integrity: sha512-UxowFKnAFIwtmSxgKjWAVgjE3Fk7MQJT0ZIyl0NwIFZTrx4913rLaonGJ84V+x/2+w/pe4ULHRns+GZPs1TVuw==} + dependencies: + glob: 7.1.2 + minimatch: 3.0.4 + dev: true + + /fill-range@2.2.3: + resolution: {integrity: sha512-P1WnpaJQ8BQdSEIjEmgyCHm9ESwkO6sMu+0Moa4s0u9B+iQ5M9tBbbCYvWmF7vRvqyMO2ENqC+w4Hev8wErQcg==} + engines: {node: '>=0.10.0'} + dependencies: + is-number: 2.1.0 + isobject: 2.1.0 + randomatic: 1.1.7 + repeat-element: 1.1.2 + repeat-string: 1.6.1 + dev: true + + /find-up@1.1.2: + resolution: {integrity: sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==} + engines: {node: '>=0.10.0'} + dependencies: + path-exists: 2.1.0 + pinkie-promise: 2.0.1 + dev: true + + /find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + dependencies: + locate-path: 2.0.0 + dev: true + + /for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + dev: true + + /for-own@0.1.5: + resolution: {integrity: sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==} + engines: {node: '>=0.10.0'} + dependencies: + for-in: 1.0.2 + dev: true + + /foreach@2.0.5: + resolution: {integrity: sha512-ZBbtRiapkZYLsqoPyZOR+uPfto0GRMNQN1GwzZtZt7iZvPPbDDQV0JF5Hx4o/QFQ5c0vyuoZ98T8RSBbopzWtA==} + dev: true + + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: true + + /form-data@2.3.1: + resolution: {integrity: sha512-ZznzvgkNMfVvSHP0rlg09OeW/g7ib4+NpwNGxLFJOrwUcjN0O8OUASn5cvnpnWve9ZlzW6GUa6NhhlCdb6DqCw==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.5 + mime-types: 2.1.17 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@1.1.3: + resolution: {integrity: sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==} + engines: {node: '>=0.8.0'} + os: [darwin] + deprecated: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. + requiresBuild: true + dependencies: + nan: 2.8.0 + dev: true + optional: true + bundledDependencies: + - node-pre-gyp + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /get-caller-file@1.0.2: + resolution: {integrity: sha512-A6srK23btrgde1mUYEzplvRPjdwkZXrHsIRNRZnG5p8ZEJHG+QB8ENw16MtH7NWiyDGiSF2giAlJpcls/y2wxQ==} + dev: true + + /get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + dev: true + + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: true + + /glob-base@0.3.0: + resolution: {integrity: sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==} + engines: {node: '>=0.10.0'} + dependencies: + glob-parent: 2.0.0 + is-glob: 2.0.1 + dev: true + + /glob-parent@2.0.0: + resolution: {integrity: sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==} + dependencies: + is-glob: 2.0.1 + dev: true + + /glob@7.1.2: + resolution: {integrity: sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.3 + minimatch: 3.0.4 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@9.18.0: + resolution: {integrity: sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==} + engines: {node: '>=0.10.0'} + dev: true + + /graceful-fs@4.1.11: + resolution: {integrity: sha512-9x6DLUuW+ROFdMTII9ec9t/FK8va6kYcC8/LggumssLM8kNv7IdFl3VrNUqgir2tJuBVxBga1QBoRziZacO5Zg==} + engines: {node: '>=0.4.0'} + dev: true + + /growly@1.3.0: + resolution: {integrity: sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==} + dev: true + + /handlebars@4.0.10: + resolution: {integrity: sha512-QOJedxEjsSijGxDpK4pq2QLEGKrX+f7LbZZwhiYV68oi1pNIoQOi91phTdALHfah9zdqW1UxRAa4/8BFxj9FtQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + async: 1.5.2 + optimist: 0.6.1 + source-map: 0.4.4 + optionalDependencies: + uglify-js: 2.8.29 + dev: true + + /har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + dev: true + + /har-validator@5.0.3: + resolution: {integrity: sha512-r7LZkP7Z6WMxj5zARzB9dSpIKu/sp0NfHIgtj6kmQXhEArNctjB5FEv/L2XfLdWqIocPT2QVt0LFOlEUioTBtQ==} + engines: {node: '>=4'} + deprecated: this library is no longer supported + dependencies: + ajv: 5.5.2 + har-schema: 2.0.0 + dev: true + + /has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /has-flag@1.0.0: + resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} + engines: {node: '>=0.10.0'} + dev: true + + /has-flag@2.0.0: + resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} + engines: {node: '>=0.10.0'} + dev: true + + /has@1.0.1: + resolution: {integrity: sha512-8wpov6mGFPJ/SYWGQIFo6t0yuNWoO9MkSq3flX8LhiGmbIUhDETp9knPMcIm0Xig1ybWsw6gq2w0gCz1JHD+Qw==} + engines: {node: '>= 0.8.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hawk@6.0.2: + resolution: {integrity: sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==} + engines: {node: '>=4.5.0'} + deprecated: This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues. + dependencies: + boom: 4.3.1 + cryptiles: 3.1.2 + hoek: 4.2.0 + sntp: 2.1.0 + dev: true + + /hoek@4.2.0: + resolution: {integrity: sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==} + engines: {node: '>=4.0.0'} + deprecated: This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial). + dev: true + + /home-or-tmp@2.0.0: + resolution: {integrity: sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==} + engines: {node: '>=0.10.0'} + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + dev: true + + /hosted-git-info@2.5.0: + resolution: {integrity: sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==} + dev: true + + /html-encoding-sniffer@1.0.1: + resolution: {integrity: sha512-mZeyJClkfuKBpYabLFSeHsbcOU8eZQcSqSxfuaazMkyMIbJXZPu546YZPXdDeSdkwfEKm7E363XNlU4QYBEh8Q==} + dependencies: + whatwg-encoding: 1.0.1 + dev: true + + /http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.1 + sshpk: 1.13.1 + dev: true + + /iconv-lite@0.4.13: + resolution: {integrity: sha512-QwVuTNQv7tXC5mMWFX5N5wGjmybjNBBD8P3BReTkPmipoxTUFgWM2gXNvldHQr6T14DH0Dh6qBVg98iJt7u4mQ==} + engines: {node: '>=0.8.0'} + dev: true + + /iconv-lite@0.4.19: + resolution: {integrity: sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==} + engines: {node: '>=0.10.0'} + dev: false + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + dev: true + + /invariant@2.2.2: + resolution: {integrity: sha512-FUiAFCOgp7bBzHfa/fK+Uc/vqywvdN9Wg3CiTprLcE630mrhxjDS5MlBkHzeI6+bC/6bq9VX/hxBt05fPAT5WA==} + dependencies: + loose-envify: 1.3.1 + dev: true + + /invert-kv@1.0.0: + resolution: {integrity: sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-buffer@1.1.5: + resolution: {integrity: sha512-miqftL8E53hH0dtQqLdN+3JwClyJiITcif3gy+RiUlnLJUhEwdyRC29/gpYbuC9IhazGSnP8TjbvxWw2AZylWQ==} + deprecated: This version of 'is-buffer' is out-of-date. You must update to v1.1.6 or newer + dev: true + + /is-builtin-module@1.0.0: + resolution: {integrity: sha512-C2wz7Juo5pUZTFQVer9c+9b4qw3I5T/CHQxQyhVu7BJel6C22FmsLIWsdseYyOw6xz9Pqy9eJWSkQ7+3iN1HVw==} + engines: {node: '>=0.10.0'} + dependencies: + builtin-modules: 1.1.1 + dev: true + + /is-callable@1.1.3: + resolution: {integrity: sha512-gcmUh1kFielP0yJSKD+A1aOPNlI8ZzruhHum+Geq6M3Ibx5JnwcsTJCktWj+reKIjjtefToy/u8YNRUZq4FHuQ==} + engines: {node: '>= 0.4'} + dev: true + + /is-ci@1.0.10: + resolution: {integrity: sha512-XLNo1nE+4BKdFApu+c/uOubwwpw0up/JYH2D9Ut6g+rXxlunxUur/7WIkkprfqwtTe2cCCaXA/DOc/iS+8m/hA==} + dependencies: + ci-info: 1.0.0 + dev: true + + /is-date-object@1.0.1: + resolution: {integrity: sha512-P5rExV1phPi42ppoMWy7V63N3i173RY921l4JJ7zonMSxK+OWGPj76GD+cUKUb68l4vQXcJp2SsG+r/A4ABVzg==} + engines: {node: '>= 0.4'} + dev: true + + /is-dotfile@1.0.3: + resolution: {integrity: sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-equal-shallow@0.1.3: + resolution: {integrity: sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==} + engines: {node: '>=0.10.0'} + dependencies: + is-primitive: 2.0.0 + dev: true + + /is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + dev: true + + /is-extglob@1.0.0: + resolution: {integrity: sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==} + engines: {node: '>=0.10.0'} + dev: true + + /is-finite@1.0.2: + resolution: {integrity: sha512-e+gU0KGrlbqjEcV80SAqg4g7PQYOm3/IrdwAJ+kPwHqGhLKhtuTJGGxGtrsc8RXlHt2A8Vlnv+79Vq2B1GQasg==} + engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: true + + /is-fullwidth-code-point@1.0.0: + resolution: {integrity: sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==} + engines: {node: '>=0.10.0'} + dependencies: + number-is-nan: 1.0.1 + dev: true + + /is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: true + + /is-glob@2.0.1: + resolution: {integrity: sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 1.0.0 + dev: true + + /is-number@2.1.0: + resolution: {integrity: sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-number@3.0.0: + resolution: {integrity: sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + dev: true + + /is-posix-bracket@0.1.1: + resolution: {integrity: sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-primitive@2.0.0: + resolution: {integrity: sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==} + engines: {node: '>=0.10.0'} + dev: true + + /is-regex@1.0.4: + resolution: {integrity: sha512-WQgPrEkb1mPCWLSlLFuN1VziADSixANugwSkJfPRR73FNWIQQN+tR/t1zWfyES/Y9oag/XBtVsahFdfBku3Kyw==} + engines: {node: '>= 0.4'} + dependencies: + has: 1.0.1 + dev: true + + /is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + /is-symbol@1.0.1: + resolution: {integrity: sha512-Z1cLAG7dXM1vJv8mAGjA+XteO0YzYPwD473+qPAWKycNZxwCH/I56QIohKGYCZSB7j6tajrxi/FvOpAfqGhhRQ==} + engines: {node: '>= 0.4'} + dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: true + + /is-utf8@0.2.1: + resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /isobject@2.1.0: + resolution: {integrity: sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==} + engines: {node: '>=0.10.0'} + dependencies: + isarray: 1.0.0 + dev: true + + /isomorphic-fetch@2.2.1: + resolution: {integrity: sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==} + dependencies: + whatwg-fetch: 2.0.3 + dev: false + + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: true + + /istanbul-api@1.2.1: + resolution: {integrity: sha512-oFCwXvd65amgaPCzqrR+a2XjanS1MvpXN6l/MlMUTv6uiA1NOgGX+I0uyq8Lg3GDxsxPsaP1049krz3hIJ5+KA==} + dependencies: + async: 2.5.0 + fileset: 2.0.3 + istanbul-lib-coverage: 1.1.1 + istanbul-lib-hook: 1.1.0 + istanbul-lib-instrument: 1.9.1 + istanbul-lib-report: 1.1.2 + istanbul-lib-source-maps: 1.2.2 + istanbul-reports: 1.1.3 + js-yaml: 3.9.1 + mkdirp: 0.5.1 + once: 1.4.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-coverage@1.1.1: + resolution: {integrity: sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==} + dev: true + + /istanbul-lib-hook@1.1.0: + resolution: {integrity: sha512-U3qEgwVDUerZ0bt8cfl3dSP3S6opBoOtk3ROO5f2EfBr/SRiD9FQqzwaZBqFORu8W7O0EXpai+k7kxHK13beRg==} + dependencies: + append-transform: 0.4.0 + dev: true + + /istanbul-lib-instrument@1.9.1: + resolution: {integrity: sha512-RQmXeQ7sphar7k7O1wTNzVczF9igKpaeGQAG9qR2L+BS4DCJNTI9nytRmIVYevwO0bbq+2CXvJmYDuz0gMrywA==} + dependencies: + babel-generator: 6.26.0 + babel-template: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + istanbul-lib-coverage: 1.1.1 + semver: 5.4.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@1.1.2: + resolution: {integrity: sha512-UTv4VGx+HZivJQwAo1wnRwe1KTvFpfi/NYwN7DcsrdzMXwpRT/Yb6r4SBPoHWj4VuQPakR32g4PUUeyKkdDkBA==} + dependencies: + istanbul-lib-coverage: 1.1.1 + mkdirp: 0.5.1 + path-parse: 1.0.5 + supports-color: 3.2.3 + dev: true + + /istanbul-lib-source-maps@1.2.2: + resolution: {integrity: sha512-8BfdqSfEdtip7/wo1RnrvLpHVEd8zMZEDmOFEnpC6dg0vXflHt9nvoAyQUzig2uMSXfF2OBEYBV3CVjIL9JvaQ==} + dependencies: + debug: 3.1.0 + istanbul-lib-coverage: 1.1.1 + mkdirp: 0.5.1 + rimraf: 2.6.1 + source-map: 0.5.7 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@1.1.3: + resolution: {integrity: sha512-ZEelkHh8hrZNI5xDaKwPMFwDsUf5wIEI2bXAFGp1e6deR2mnEKBPhLJEgr4ZBt8Gi6Mj38E/C8kcy9XLggVO2Q==} + dependencies: + handlebars: 4.0.10 + dev: true + + /jest-changed-files@22.0.3: + resolution: {integrity: sha512-CG7eNJNO9x1O/3J4Uhe2QXra1MnC9+KS1f2NeOg+7iQ+8dDCgxCtpusmKfu44TnEyKwkIDhDr6htPfPaI+Fwbw==} + dependencies: + throat: 4.1.0 + dev: true + + /jest-cli@22.0.4: + resolution: {integrity: sha512-f1lZRM13IwIINzjE3RebXQKtQLiKncpSrbJZ/aTZJXmzEWGdgSayW4ESyhU+xK3uGiJEUSzbHjwPY6nGJ8VbUA==} + engines: {node: '>= 6'} + hasBin: true + dependencies: + ansi-escapes: 3.0.0 + chalk: 2.0.1 + glob: 7.1.2 + graceful-fs: 4.1.11 + is-ci: 1.0.10 + istanbul-api: 1.2.1 + istanbul-lib-coverage: 1.1.1 + istanbul-lib-instrument: 1.9.1 + istanbul-lib-source-maps: 1.2.2 + jest-changed-files: 22.0.3 + jest-config: 22.0.4 + jest-environment-jsdom: 22.0.4 + jest-get-type: 22.0.3 + jest-haste-map: 22.0.3 + jest-message-util: 22.0.3 + jest-regex-util: 22.0.3 + jest-resolve-dependencies: 22.0.3 + jest-runner: 22.0.4 + jest-runtime: 22.0.4 + jest-snapshot: 22.0.3 + jest-util: 22.0.4 + jest-worker: 22.0.3 + micromatch: 2.3.11 + node-notifier: 5.1.2 + realpath-native: 1.0.0 + rimraf: 2.6.1 + slash: 1.0.0 + string-length: 2.0.0 + strip-ansi: 4.0.0 + which: 1.3.0 + yargs: 10.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-config@22.0.4: + resolution: {integrity: sha512-NcBeixqHjHDZO9+pUj+365LQV2s65d2f0/IrwlUyv0xaJovRNc6eDvoJ/r2UUlHnqjP3Go+R0ECUsXPXjk4SHw==} + dependencies: + chalk: 2.0.1 + glob: 7.1.2 + jest-environment-jsdom: 22.0.4 + jest-environment-node: 22.0.4 + jest-get-type: 22.0.3 + jest-jasmine2: 22.0.4 + jest-regex-util: 22.0.3 + jest-resolve: 22.0.4 + jest-util: 22.0.4 + jest-validate: 22.0.3 + pretty-format: 22.0.3 + dev: true + + /jest-diff@22.0.3: + resolution: {integrity: sha512-Y7xN9Lc/NgFvR14lvjrJXB6x2x1LLe5NnMyzLvilBSSOyjy9uAVnR2Bt1YgzdfRrfaxsx7xFUVcqXLUnPkrJcA==} + dependencies: + chalk: 2.0.1 + diff: 3.3.0 + jest-get-type: 22.0.3 + pretty-format: 22.0.3 + dev: true + + /jest-docblock@22.0.3: + resolution: {integrity: sha512-LhviP2rqIg2IzS6m97W7T032oMrT699Tr6Njjhhl4FCLj+75BUy9CsSmGgfoVEql1uc+myBkssvcbn7T9xDR+A==} + dependencies: + detect-newline: 2.1.0 + dev: true + + /jest-environment-jsdom@22.0.4: + resolution: {integrity: sha512-vnjefLZlsNsmnjKcaXkx2IxTBNG40vfRVOdMfcfkPkq85JxFB7wzNtjLx+RIfiNpIZd04C1PXbF0aJIenY85Ng==} + dependencies: + jest-mock: 22.0.3 + jest-util: 22.0.4 + jsdom: 11.5.1 + dev: true + + /jest-environment-node@22.0.4: + resolution: {integrity: sha512-9vjNKb86UivvKCZCudMNixQgdMnOG7ql6iVYnaiK0CmvZ0WQD+mlM10NvgiWpRv4HstcnRL1pY/GSIHXAD6qXw==} + dependencies: + jest-mock: 22.0.3 + jest-util: 22.0.4 + dev: true + + /jest-get-type@22.0.3: + resolution: {integrity: sha512-TaJnc/lnJQ3jwry+NUWkqaJmKrM/Ut3XdK89HfiqdI3DMRLd6Zb4wyKjwuNP37MEQqlNg0YWH4sbBR8D4exjCA==} + dev: true + + /jest-haste-map@22.0.3: + resolution: {integrity: sha512-VosIMOFQFu1rTF+MvOWVuv2KVmZ9eTkRgfwW2yUAs6/AhwmIfXRl/tih+fIOYcHzU4Auu1G8Fvl2kkF5g0k6/A==} + dependencies: + fb-watchman: 2.0.0 + graceful-fs: 4.1.11 + jest-docblock: 22.0.3 + jest-worker: 22.0.3 + micromatch: 2.3.11 + sane: 2.2.0 + dev: true + + /jest-jasmine2@22.0.4: + resolution: {integrity: sha512-pn1XPHUkffHK6oNY1Dfl/+Rg0UuTdlg3aGDnjyK6dZzGEBeiH1uKuSgZEjy3Lj461l3atpzsQyw7ilXPyjFnUw==} + dependencies: + callsites: 2.0.0 + chalk: 2.0.1 + expect: 22.0.3 + graceful-fs: 4.1.11 + jest-diff: 22.0.3 + jest-matcher-utils: 22.0.3 + jest-message-util: 22.0.3 + jest-snapshot: 22.0.3 + source-map-support: 0.5.0 + dev: true + + /jest-leak-detector@22.0.3: + resolution: {integrity: sha512-xyVdAmcG8M3jWtVeadDUU6MAHLBrjkP4clz2UtTZ1gpe5bRLk27VjQOpzTwK20MkV/6iZQhSuRVuzHS5kD0HpA==} + dependencies: + pretty-format: 22.0.3 + optionalDependencies: + weak: 1.0.1 + dev: true + + /jest-matcher-utils@22.0.3: + resolution: {integrity: sha512-FJbKpCR3K7YYE/Pnvy5OrLFgPEswpYWIfVtdwT2NC6pBARbYGX39KF3bTxS9yg2mv0YL2zHe3UbwzFsi9nFpVA==} + dependencies: + chalk: 2.0.1 + jest-get-type: 22.0.3 + pretty-format: 22.0.3 + dev: true + + /jest-message-util@22.0.3: + resolution: {integrity: sha512-AVBdCx7Oj5wBpMOH089lx7Zgwpdz9HbReA82HuVAlIT4kEQRvCy6Sl9yVWDGJwHTgB/OYQGkgmbv/P/K8TkWNw==} + dependencies: + '@babel/code-frame': 7.0.0-beta.35 + chalk: 2.0.1 + micromatch: 2.3.11 + slash: 1.0.0 + stack-utils: 1.0.1 + dev: true + + /jest-mock@22.0.3: + resolution: {integrity: sha512-donODXcDG03EAEavc9xfJ7fBF/LNVjoZYkmj9DLrQ1B9YcT6wh8Xx7IYg25b8V/8F/eXPMAE0KK5q6Fqe6yAeg==} + dev: true + + /jest-regex-util@22.0.3: + resolution: {integrity: sha512-mplC9chiAotES3ClzNhy0SJcfHB2DivooKJZW+2hDdvP8LLB+OUI+D6bJd7sncbKUsyFcmblEvpm/zz/hef7HA==} + dev: true + + /jest-resolve-dependencies@22.0.3: + resolution: {integrity: sha512-u9MUNJIa9GJ0YFhvM0+Scr4tyX84nC42d3w18Cly1doY7pTT+9momm+TncpuDlFyB2aNmS8SfdEbiLr1e6tBwg==} + dependencies: + jest-regex-util: 22.0.3 + dev: true + + /jest-resolve@22.0.4: + resolution: {integrity: sha512-yoxHsX4MTT2Ra/dFia9VCunzsA/4jMBENMmLjREIUkCIP1edk/PZUOGVVf680Gw04CtmT5stETylcbmbL7hJBw==} + dependencies: + browser-resolve: 1.11.2 + chalk: 2.0.1 + dev: true + + /jest-runner@22.0.4: + resolution: {integrity: sha512-srBkbqmiSB+jzSaG652fmi3kS6rV6wS/4fOG8dxxBg3dCqNQcM2/L3TI3ZK0SwIAcdGJh5Gybs8aDboT8K9Cdw==} + dependencies: + jest-config: 22.0.4 + jest-docblock: 22.0.3 + jest-haste-map: 22.0.3 + jest-jasmine2: 22.0.4 + jest-leak-detector: 22.0.3 + jest-message-util: 22.0.3 + jest-runtime: 22.0.4 + jest-util: 22.0.4 + jest-worker: 22.0.3 + throat: 4.1.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-runtime@22.0.4: + resolution: {integrity: sha512-+7uEwf/4f8k1E/eViyGK6/M5yA4O3f6TdWViuqF9MV7vXwG2OVJu8YEZa5239nEnHJiwinXp4eZXX+HB4pQRPg==} + hasBin: true + dependencies: + babel-core: 6.26.0 + babel-jest: 22.0.4(babel-core@6.26.0) + babel-plugin-istanbul: 4.1.5 + chalk: 2.0.1 + convert-source-map: 1.5.1 + graceful-fs: 4.1.11 + jest-config: 22.0.4 + jest-haste-map: 22.0.3 + jest-regex-util: 22.0.3 + jest-resolve: 22.0.4 + jest-util: 22.0.4 + json-stable-stringify: 1.0.1 + micromatch: 2.3.11 + realpath-native: 1.0.0 + slash: 1.0.0 + strip-bom: 3.0.0 + write-file-atomic: 2.3.0 + yargs: 10.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-snapshot@22.0.3: + resolution: {integrity: sha512-e/a/EvMsY5XROWy4QWX6PvYziuJ8ttD6+QcnbogODWtx2LGhvVQOb7pmqGTo0tL/p0vzFetZA9GlZSh/EfMepg==} + dependencies: + chalk: 2.0.1 + jest-diff: 22.0.3 + jest-matcher-utils: 22.0.3 + mkdirp: 0.5.1 + natural-compare: 1.4.0 + pretty-format: 22.0.3 + dev: true + + /jest-util@22.0.4: + resolution: {integrity: sha512-gNNPtcCFkVh7daKIl3/06eoQ90QXGXCyDOfyZ3IEyTWmHBdX3GvklcOtyGcdOvrYEubaZTfMcMKmEeo/6sRTog==} + dependencies: + callsites: 2.0.0 + chalk: 2.0.1 + graceful-fs: 4.1.11 + is-ci: 1.0.10 + jest-message-util: 22.0.3 + jest-validate: 22.0.3 + mkdirp: 0.5.1 + dev: true + + /jest-validate@22.0.3: + resolution: {integrity: sha512-GmlLmPCtrSQ3iB4A1uxcfjawaaQnwESCDcUg5tMxJKeBbmPdcWPAb6EWzvANxULPUV7hfPKLwg4xIPpi7cx1/g==} + dependencies: + chalk: 2.0.1 + jest-get-type: 22.0.3 + leven: 2.1.0 + pretty-format: 22.0.3 + dev: true + + /jest-worker@22.0.3: + resolution: {integrity: sha512-fPdCTnogFQiR0CP6whEsIly2RfcHxvalqyLjhui6qa1SnOmHiX7L8k4Umo8CBIp5ndWY0+ej1o7OTE5MlzPabg==} + dependencies: + merge-stream: 1.0.1 + dev: true + + /jest@22.0.4: + resolution: {integrity: sha512-S0tmgK5psULvt/11QzgAZWGpY5y5TkMRzd3T21Q13JzTx37Vx6F0Nw022c9Kc/IbEy+AHkKkGFVO5QafE8MrDg==} + engines: {node: '>= 6'} + hasBin: true + dependencies: + jest-cli: 22.0.4 + transitivePeerDependencies: + - supports-color + dev: true + + /js-tokens@3.0.2: + resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} + dev: true + + /js-yaml@3.9.1: + resolution: {integrity: sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==} + hasBin: true + dependencies: + argparse: 1.0.9 + esprima: 4.0.0 + dev: true + + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: true + optional: true + + /jsdom@11.5.1: + resolution: {integrity: sha512-89ztIZ03aYK9f1uUrLXLsZndRge/JnZjzjpaN+lrse3coqz+8PR/dX4WLHpbF5fIKTXhDjFODOJw2328lPJ90g==} + dependencies: + abab: 1.0.3 + acorn: 5.2.1 + acorn-globals: 4.1.0 + array-equal: 1.0.0 + browser-process-hrtime: 0.1.2 + content-type-parser: 1.0.1 + cssom: 0.3.2 + cssstyle: 0.2.37 + domexception: 1.0.0 + escodegen: 1.9.0 + html-encoding-sniffer: 1.0.1 + left-pad: 1.2.0 + nwmatcher: 1.4.3 + parse5: 3.0.3 + pn: 1.0.0 + request: 2.83.0 + request-promise-native: 1.0.5(request@2.83.0) + sax: 1.2.4 + symbol-tree: 3.2.2 + tough-cookie: 2.3.3 + webidl-conversions: 4.0.2 + whatwg-encoding: 1.0.1 + whatwg-url: 6.4.0 + xml-name-validator: 2.0.1 + dev: true + + /jsesc@1.3.0: + resolution: {integrity: sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==} + hasBin: true + dev: true + + /json-schema-traverse@0.3.1: + resolution: {integrity: sha512-4JD/Ivzg7PoW8NzdrBSr3UFwC9mHgvI7Z6z3QGBsSHgKaRTUDmyZAAKJo2UbG1kUVfS9WS8bi36N49U1xw43DA==} + dev: true + + /json-schema@0.2.3: + resolution: {integrity: sha512-a3xHnILGMtk+hDOqNwHzF6e2fNbiMrXZvxKQiEv2MlgQP+pjIOzqAmKYD2mDpXYE/44M7g+n9p2bKkYWDUcXCQ==} + dev: true + + /json-stable-stringify@1.0.1: + resolution: {integrity: sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==} + dependencies: + jsonify: 0.0.0 + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /json5@0.5.1: + resolution: {integrity: sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==} + hasBin: true + dev: true + + /jsonify@0.0.0: + resolution: {integrity: sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==} + dev: true + + /jsprim@1.4.1: + resolution: {integrity: sha512-4Dj8Rf+fQ+/Pn7C5qeEX02op1WfOss3PKTE9Nsop3Dx+6UPxlm1dr/og7o2cRa5hNN07CACr4NFzRLtj/rjWog==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.2.3 + verror: 1.10.0 + dev: true + + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.5 + dev: true + + /kind-of@4.0.0: + resolution: {integrity: sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.5 + dev: true + + /lazy-cache@1.0.4: + resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==} + engines: {node: '>=0.10.0'} + dev: true + optional: true + + /lcid@1.0.0: + resolution: {integrity: sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==} + engines: {node: '>=0.10.0'} + dependencies: + invert-kv: 1.0.0 + dev: true + + /left-pad@1.2.0: + resolution: {integrity: sha512-OQadpCyFCT/VLniZQgym8d3/ofIJtuZyw2ibsVeIUOexKgW/osn8+mMFJbwGMPeDC4GnLzD8q115WPCDx4YRWg==} + deprecated: use String.prototype.padStart() + dev: true + + /leven@2.1.0: + resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==} + engines: {node: '>=0.10.0'} + dev: true + + /levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + dev: true + + /load-json-file@1.1.0: + resolution: {integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==} + engines: {node: '>=0.10.0'} + dependencies: + graceful-fs: 4.1.11 + parse-json: 2.2.0 + pify: 2.3.0 + pinkie-promise: 2.0.1 + strip-bom: 2.0.0 + dev: true + + /locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + dev: true + + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + + /lodash@4.17.4: + resolution: {integrity: sha512-6X37Sq9KCpLSXEh8uM12AKYlviHPNNk4RxiGBn4cmKGJinbXBneWIV7iE/nXkM928O7ytHcHb6+X6Svl0f4hXg==} + dev: true + + /longest@1.0.1: + resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} + engines: {node: '>=0.10.0'} + dev: true + optional: true + + /loose-envify@1.3.1: + resolution: {integrity: sha512-iG/U770U9HaHmy0u+fSyxSIclZ3d9WPFtGjV2drWW0SthBnQ1Fa/SCKIaGLAVwYzrBGEPx9gen047er+MCUgnQ==} + hasBin: true + dependencies: + js-tokens: 3.0.2 + dev: true + + /lru-cache@4.1.1: + resolution: {integrity: sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==} + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + dev: true + + /makeerror@1.0.11: + resolution: {integrity: sha512-M/XvMZ6oK4edXjvg/ZYyzByg8kjpVrF/m0x3wbhOlzJfsQgFkqP1rJnLnJExOcslmLSSeLiN6NmF+cBoKJHGTg==} + dependencies: + tmpl: 1.0.4 + dev: true + + /mem@1.1.0: + resolution: {integrity: sha512-nOBDrc/wgpkd3X/JOhMqYR+/eLqlfLP4oQfoBA6QExIxEl+GU01oyEkwWyueyO8110pUKijtiHGhEmYoOn88oQ==} + engines: {node: '>=4'} + dependencies: + mimic-fn: 1.1.0 + dev: true + + /merge-stream@1.0.1: + resolution: {integrity: sha512-e6RM36aegd4f+r8BZCcYXlO2P3H6xbUM6ktL2Xmf45GAOit9bI4z6/3VU7JwllVO1L7u0UDSg/EhzQ5lmMLolA==} + dependencies: + readable-stream: 2.3.3 + dev: true + + /merge@1.2.0: + resolution: {integrity: sha512-3GGUnRRpmQMsRpuMbW26z/raenVYeYXcGR1qBGvlHmPq5jaXqL1Zqgdh/0bRw+mTE6F2oTjCj8Tb/wUOy61/CA==} + dev: true + + /micromatch@2.3.11: + resolution: {integrity: sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==} + engines: {node: '>=0.10.0'} + dependencies: + arr-diff: 2.0.0 + array-unique: 0.2.1 + braces: 1.8.5 + expand-brackets: 0.1.5 + extglob: 0.3.2 + filename-regex: 2.0.1 + is-extglob: 1.0.0 + is-glob: 2.0.1 + kind-of: 3.2.2 + normalize-path: 2.1.1 + object.omit: 2.0.1 + parse-glob: 3.0.4 + regex-cache: 0.4.3 + dev: true + + /mime-db@1.30.0: + resolution: {integrity: sha512-SUaL89ROHF5P6cwrhLxE1Xmk60cFcctcJl3zwMeQWcoQzt0Al/X8qxUz2gi19NECqYspzbYpAJryIRnLcjp20g==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.17: + resolution: {integrity: sha512-rOFZoFAbaupSpzARUe5CU1P9mwfX+lIFAuj0soNsEZEnrHu6LZNyV7/FClEB/oF9A1o5KStlumRjW6D4Q2FRCA==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.30.0 + dev: true + + /mimic-fn@1.1.0: + resolution: {integrity: sha512-h1HSEmsL/ggPjnixiDrEdt2YmXDpeSQlT26BMutTYBxJ46L3nOybRl/aNh/i623y6suDlbgF+m1dqX5V1eCBBQ==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.0.4: + resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} + dependencies: + brace-expansion: 1.1.8 + dev: true + + /minimist@0.0.8: + resolution: {integrity: sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==} + dev: true + + /minimist@1.2.0: + resolution: {integrity: sha512-7Wl+Jz+IGWuSdgsQEJ4JunV0si/iMhg42MnQQG6h1R6TNeVenp4U9x5CC5v/gYqz/fENLQITAWXidNtVL0NNbw==} + dev: true + + /mkdirp@0.5.1: + resolution: {integrity: sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==} + deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.) + hasBin: true + dependencies: + minimist: 0.0.8 + dev: true + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: true + + /nan@2.8.0: + resolution: {integrity: sha512-kBTsZNixwSmgVRl1nIVCkQzqRmosFpnY/pLPYo8xC7Mu9ehnKkbrMsM4xb889UafRGLqJ58hKZp+Dn4XVP9Bpg==} + dev: true + optional: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-notifier@5.1.2: + resolution: {integrity: sha512-HJp4p6fq5IlsFsjQFfhaZWfbUMfDiaSDZ5Wr/9g9Huwh+KFk0FdW8sjBLjk1bReQc4KPr9xUd/KBcsluCY8L/A==} + dependencies: + growly: 1.3.0 + semver: 5.4.1 + shellwords: 0.1.1 + which: 1.3.0 + dev: true + + /normalize-package-data@2.4.0: + resolution: {integrity: sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==} + dependencies: + hosted-git-info: 2.5.0 + is-builtin-module: 1.0.0 + semver: 5.4.1 + validate-npm-package-license: 3.0.1 + dev: true + + /normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.0.2 + dev: true + + /npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + dependencies: + path-key: 2.0.1 + dev: true + + /number-is-nan@1.0.1: + resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} + engines: {node: '>=0.10.0'} + dev: true + + /nwmatcher@1.4.3: + resolution: {integrity: sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw==} + dev: true + + /oauth-sign@0.8.2: + resolution: {integrity: sha512-VlF07iu3VV3+BTXj43Nmp6Irt/G7j/NgEctUS6IweH1RGhURjjCc2NWtzXFPXXWWfc7hgbXQdtiQu2LGp6MxUg==} + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-keys@1.0.11: + resolution: {integrity: sha512-I0jUsqFqmQFOIhQQFlW8QDuX3pVqUWkiiavYj8+TBiS7m+pM9hPCxSnYWqL1hHMBb7BbQ2HidT+6CZ8/BT/ilw==} + engines: {node: '>= 0.4'} + dev: true + + /object.getownpropertydescriptors@2.0.3: + resolution: {integrity: sha512-NwrpYtu1CSNWdNgcEvLmHOHjhMeglj22YJpg/ezASfIFYqNK4F94iUxKRPnRNbOuOMoQb5JS+6Ebi16xtYZbqQ==} + engines: {node: '>= 0.8'} + dependencies: + define-properties: 1.1.2 + es-abstract: 1.10.0 + dev: true + + /object.omit@2.0.1: + resolution: {integrity: sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==} + engines: {node: '>=0.10.0'} + dependencies: + for-own: 0.1.5 + is-extendable: 0.1.1 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optimist@0.6.1: + resolution: {integrity: sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==} + dependencies: + minimist: 0.0.8 + wordwrap: 0.0.2 + dev: true + + /optionator@0.8.2: + resolution: {integrity: sha512-oCOQ8AIC2ciLy/sE2ehafRBleBgDLvzGhBRRev87sP7ovnbvQfqpc3XFI0DhHey2OfVoNV91W+GPC6B3540/5Q==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.3 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + wordwrap: 1.0.0 + dev: true + + /os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + dev: true + + /os-locale@2.1.0: + resolution: {integrity: sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==} + engines: {node: '>=4'} + dependencies: + execa: 0.7.0 + lcid: 1.0.0 + mem: 1.1.0 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + dev: true + + /p-limit@1.1.0: + resolution: {integrity: sha512-sFSFmsGcVho1dNzsPGyiL1xs4KxZlM2QlznVxCDg0loLefThSsVkZPyBZEehQSci0nLwkgPZziJYpMGa59Vzqw==} + engines: {node: '>=4'} + dev: true + + /p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + dependencies: + p-limit: 1.1.0 + dev: true + + /parse-glob@3.0.4: + resolution: {integrity: sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==} + engines: {node: '>=0.10.0'} + dependencies: + glob-base: 0.3.0 + is-dotfile: 1.0.3 + is-extglob: 1.0.0 + is-glob: 2.0.1 + dev: true + + /parse-json@2.2.0: + resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} + engines: {node: '>=0.10.0'} + dependencies: + error-ex: 1.3.1 + dev: true + + /parse5@3.0.3: + resolution: {integrity: sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==} + dependencies: + '@types/node': 8.5.2 + dev: true + + /path-exists@2.1.0: + resolution: {integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==} + engines: {node: '>=0.10.0'} + dependencies: + pinkie-promise: 2.0.1 + dev: true + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + dev: true + + /path-parse@1.0.5: + resolution: {integrity: sha512-u4e4H/UUeMbJ1UnBnePf6r4cm4fFZs57BMocUSFeea807JTYk2HJnE9GjUpWHaDZk1OQGoArnWW1yEo9nd57ww==} + dev: true + + /path-type@1.1.0: + resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==} + engines: {node: '>=0.10.0'} + dependencies: + graceful-fs: 4.1.11 + pify: 2.3.0 + pinkie-promise: 2.0.1 + dev: true + + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: true + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pinkie-promise@2.0.1: + resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} + engines: {node: '>=0.10.0'} + dependencies: + pinkie: 2.0.4 + dev: true + + /pinkie@2.0.4: + resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} + engines: {node: '>=0.10.0'} + dev: true + + /pn@1.0.0: + resolution: {integrity: sha512-APRmKkZblvZN5iMh04Fqia+rwI41dwoqkSMY0ZBJyqO2nUyfBI07YPY5kG6xvyO3xh1faBQl7FBa2UqWCQyySQ==} + dev: true + + /prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + dev: true + + /preserve@0.2.0: + resolution: {integrity: sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==} + engines: {node: '>=0.10.0'} + dev: true + + /pretty-format@22.0.3: + resolution: {integrity: sha512-qXbDFJ2/Kk3HFIaLdOblbsCKQ09kZu4MKbXB+m/EaqD7PZ/wXe2XcRREmQleMh4wmerxlma6eJTh3nxCXYUmmA==} + dependencies: + ansi-regex: 3.0.0 + ansi-styles: 3.2.0 + dev: true + + /private@0.1.8: + resolution: {integrity: sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==} + engines: {node: '>= 0.6'} + dev: true + + /process-nextick-args@1.0.7: + resolution: {integrity: sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw==} + dev: true + + /pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + dev: true + + /punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + dev: true + + /punycode@2.1.0: + resolution: {integrity: sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==} + engines: {node: '>=6'} + dev: true + + /qs@6.5.1: + resolution: {integrity: sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==} + engines: {node: '>=0.6'} + dev: true + + /randomatic@1.1.7: + resolution: {integrity: sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==} + engines: {node: '>= 0.10.0'} + dependencies: + is-number: 3.0.0 + kind-of: 4.0.0 + dev: true + + /read-pkg-up@1.0.1: + resolution: {integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==} + engines: {node: '>=0.10.0'} + dependencies: + find-up: 1.1.2 + read-pkg: 1.1.0 + dev: true + + /read-pkg@1.1.0: + resolution: {integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==} + engines: {node: '>=0.10.0'} + dependencies: + load-json-file: 1.1.0 + normalize-package-data: 2.4.0 + path-type: 1.1.0 + dev: true + + /readable-stream@2.3.3: + resolution: {integrity: sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==} + dependencies: + core-util-is: 1.0.2 + inherits: 2.0.3 + isarray: 1.0.0 + process-nextick-args: 1.0.7 + safe-buffer: 5.1.1 + string_decoder: 1.0.3 + util-deprecate: 1.0.2 + dev: true + + /realpath-native@1.0.0: + resolution: {integrity: sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==} + engines: {node: '>=4'} + dependencies: + util.promisify: 1.0.0 + dev: true + + /regenerator-runtime@0.11.0: + resolution: {integrity: sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==} + dev: true + + /regex-cache@0.4.3: + resolution: {integrity: sha512-mD03Qv3Lb7ncwijS5zPvJUIrIXA1XBrxIuB6/XoesvWlyJBNCk7WZa9fCnIOpTKzd6C1L+rpaxrr6t0CYFDQ+Q==} + engines: {node: '>=0.10.0'} + dependencies: + is-equal-shallow: 0.1.3 + is-primitive: 2.0.0 + dev: true + + /remove-trailing-separator@1.0.2: + resolution: {integrity: sha512-3+lgCOlL3GmoNSlALFpKkknUBambWkem5pc98c/vFCrjj2kZKgMNGP+/hedBQB/MjDvL6cIpWMwI4bRrZWa6Ig==} + dev: true + + /repeat-element@1.1.2: + resolution: {integrity: sha512-PJn5P/wQgXwp0Bpmzv9JU693QYky9P5bwntpuw8SsMXgUZHlcEyr9Vajgp/zhGSFX56/lv9Bz2k9mKrkpxLI4A==} + engines: {node: '>=0.10.0'} + dev: true + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: true + + /repeating@2.0.1: + resolution: {integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==} + engines: {node: '>=0.10.0'} + dependencies: + is-finite: 1.0.2 + dev: true + + /request-promise-core@1.1.1(request@2.83.0): + resolution: {integrity: sha512-paa/JFJUwUCx5ksokBlaGIXAvIDB+izsRU6FpHrlezFU2fj8555sKN4r+wPyql5d5Bp1ya/vrUPfVqM51v2H0g==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + dependencies: + lodash: 4.17.4 + request: 2.83.0 + dev: true + + /request-promise-native@1.0.5(request@2.83.0): + resolution: {integrity: sha512-Y75hrP+fdfWTg8R9rGNFmLi2JsZ3LlmHa+HcljiXY88NU86TaChwfkhsPN+pdojFluO2Qr0Jb+lV/aCkYpeAyw==} + engines: {node: '>=0.12.0'} + deprecated: request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + dependencies: + request: 2.83.0 + request-promise-core: 1.1.1(request@2.83.0) + stealthy-require: 1.1.1 + tough-cookie: 2.3.3 + dev: true + + /request@2.83.0: + resolution: {integrity: sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==} + engines: {node: '>= 4'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.6.0 + caseless: 0.12.0 + combined-stream: 1.0.5 + extend: 3.0.1 + forever-agent: 0.6.1 + form-data: 2.3.1 + har-validator: 5.0.3 + hawk: 6.0.2 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.17 + oauth-sign: 0.8.2 + performance-now: 2.1.0 + qs: 6.5.1 + safe-buffer: 5.1.1 + stringstream: 0.0.5 + tough-cookie: 2.3.3 + tunnel-agent: 0.6.0 + uuid: 3.1.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-main-filename@1.0.1: + resolution: {integrity: sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==} + dev: true + + /resolve@1.1.7: + resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} + dev: true + + /right-align@0.1.3: + resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + dev: true + optional: true + + /rimraf@2.6.1: + resolution: {integrity: sha512-5QIcndZ8am2WyseL6lln/utl51SwRBQs/at+zi1UnhsnPyZcAID+g0PZrKdb+kJn2fo/CwgyJweR8sP36Jer5g==} + hasBin: true + dependencies: + glob: 7.1.2 + dev: true + + /safe-buffer@5.1.1: + resolution: {integrity: sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==} + dev: true + + /sane@2.2.0: + resolution: {integrity: sha512-OSJxhHO0CgPUw3lUm3GhfREAfza45smvEI9ozuFrxKG10GHVo0ryW9FK5VYlLvxj0SV7HVKHW0voYJIRu27GWg==} + engines: {node: '>=0.6.0'} + deprecated: some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added + hasBin: true + dependencies: + anymatch: 1.3.2 + exec-sh: 0.2.0 + fb-watchman: 2.0.0 + minimatch: 3.0.4 + minimist: 1.2.0 + walker: 1.0.7 + watch: 0.18.0 + optionalDependencies: + fsevents: 1.1.3 + dev: true + + /sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + dev: true + + /semver@5.4.1: + resolution: {integrity: sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==} + hasBin: true + dev: true + + /set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + dev: true + + /shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + dependencies: + shebang-regex: 1.0.0 + dev: true + + /shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + dev: true + + /shellwords@0.1.1: + resolution: {integrity: sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==} + dev: true + + /signal-exit@3.0.2: + resolution: {integrity: sha512-meQNNykwecVxdu1RlYMKpQx4+wefIYpmxi6gexo/KAbwquJrBUrBmKYJrE8KFkVQAAVWEnwNdu21PgrD77J3xA==} + dev: true + + /slash@1.0.0: + resolution: {integrity: sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==} + engines: {node: '>=0.10.0'} + dev: true + + /sntp@2.1.0: + resolution: {integrity: sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==} + engines: {node: '>=4.0.0'} + deprecated: This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues. + dependencies: + hoek: 4.2.0 + dev: true + + /source-map-support@0.4.18: + resolution: {integrity: sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==} + dependencies: + source-map: 0.5.7 + dev: true + + /source-map-support@0.5.0: + resolution: {integrity: sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==} + dependencies: + source-map: 0.6.1 + dev: true + + /source-map@0.4.4: + resolution: {integrity: sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==} + engines: {node: '>=0.8.0'} + dependencies: + amdefine: 1.0.1 + dev: true + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /spdx-correct@1.0.2: + resolution: {integrity: sha512-A6UuuDdsSvKK2bqmUetv33zJVv0iczyaQZ536YL9+GAvbC4HceGKvXDtptnU9YZ/zGgryaFFsR4YaUCq+N/53g==} + dependencies: + spdx-license-ids: 1.2.2 + dev: true + + /spdx-expression-parse@1.0.4: + resolution: {integrity: sha512-xMXXC4eLKaIskvZm89nZi/MstVv1UtGk3nJz9BBKjreMVyoWisWFKfboH+kJS97+wUyBLpO/8ghV9M5VvrwwrA==} + dev: true + + /spdx-license-ids@1.2.2: + resolution: {integrity: sha512-qIBFhkh6ILCWNeWEe3ODFPKDYhPJrZpqdNCI2Z+w9lNdH5hoVEkfRLLbRfoIi8fb4xRYmpEOaaMH4G2pwYp/iQ==} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /sshpk@1.13.1: + resolution: {integrity: sha512-oKPL4k+ld5d737ZPB4VM99bqNb3JH+ZkxwWXR1iSPtqYbZv81hkLD7v8gmclrgR7aA8uh8ar+q0IF7gHFHg7PQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.3 + assert-plus: 1.0.0 + dashdash: 1.14.1 + getpass: 0.1.7 + optionalDependencies: + bcrypt-pbkdf: 1.0.1 + ecc-jsbn: 0.1.1 + jsbn: 0.1.1 + tweetnacl: 0.14.5 + dev: true + + /stack-utils@1.0.1: + resolution: {integrity: sha512-KeADm3hVFxp5R3yDROVatAG51zBtWTIZ8moWjz0xJrHGWzVYZjxNoJUbYJF2gyvUqQSTGsib+CgbRb+gvemV8Q==} + engines: {node: '>=0.10.0'} + dev: true + + /stealthy-require@1.1.1: + resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} + engines: {node: '>=0.10.0'} + dev: true + + /string-length@2.0.0: + resolution: {integrity: sha512-Qka42GGrS8Mm3SZ+7cH8UXiIWI867/b/Z/feQSpQx/rbfB8UGknGEZVaUQMOUVj+soY6NpWAxily63HI1OckVQ==} + engines: {node: '>=4'} + dependencies: + astral-regex: 1.0.0 + strip-ansi: 4.0.0 + dev: true + + /string-width@1.0.2: + resolution: {integrity: sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==} + engines: {node: '>=0.10.0'} + dependencies: + code-point-at: 1.1.0 + is-fullwidth-code-point: 1.0.0 + strip-ansi: 3.0.1 + dev: true + + /string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: true + + /string_decoder@1.0.3: + resolution: {integrity: sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==} + dependencies: + safe-buffer: 5.1.1 + dev: true + + /stringstream@0.0.5: + resolution: {integrity: sha512-QUQ1kThMjLRt4jA8lsn9lyIkE9bKafE7LDOL/nBBUY9Tfv2i3x1NAsVHG0uMCusFOWeeI6COhY/F20+avxRWSw==} + dev: true + + /strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + dependencies: + ansi-regex: 2.1.1 + dev: true + + /strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + dependencies: + ansi-regex: 3.0.0 + dev: true + + /strip-bom@2.0.0: + resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} + engines: {node: '>=0.10.0'} + dependencies: + is-utf8: 0.2.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + dev: true + + /supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + dev: true + + /supports-color@3.2.3: + resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} + engines: {node: '>=0.8.0'} + dependencies: + has-flag: 1.0.0 + dev: true + + /supports-color@4.2.1: + resolution: {integrity: sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==} + engines: {node: '>=4'} + dependencies: + has-flag: 2.0.0 + dev: true + + /symbol-tree@3.2.2: + resolution: {integrity: sha512-/2fldTR680SOM4zTfL9mNzf96VYFy2CyVWinf+baRrXAJ4D586mMSorV9Rk5KkK60cUrXASJMojcQsES8PaJMw==} + dev: true + + /test-exclude@4.1.1: + resolution: {integrity: sha512-35+Asrsk3XHJDBgf/VRFexPgh3UyETv8IAn/LRTiZjVy6rjPVqdEk8dJcJYBzl1w0XCJM48lvTy8SfEsCWS4nA==} + dependencies: + arrify: 1.0.1 + micromatch: 2.3.11 + object-assign: 4.1.1 + read-pkg-up: 1.0.1 + require-main-filename: 1.0.1 + dev: true + + /throat@4.1.0: + resolution: {integrity: sha512-wCVxLDcFxw7ujDxaeJC6nfl2XfHJNYs8yUYJnvMgtPEFlttP9tHSfRUv2vBe6C4hkVFPWoP1P6ZccbYjmSEkKA==} + dev: true + + /tmpl@1.0.4: + resolution: {integrity: sha512-9tP427gQBl7Mx3vzr3mquZ+Rq+1sAqIJb5dPSYEjWMYsqitxARsFCHkZS3sDptHAmrUPCZfzXNZqSuBIHdpV5A==} + dev: true + + /to-fast-properties@1.0.3: + resolution: {integrity: sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==} + engines: {node: '>=0.10.0'} + dev: true + + /tough-cookie@2.3.3: + resolution: {integrity: sha512-WR9pjSY3qO0z3yC6g33CRcVt2Wbevh0gP1XiSFql0/xRioi9qbDs3C+g4Nv2N8jmv/BloIi/SYoy/mfw5vus2A==} + engines: {node: '>=0.8'} + dependencies: + punycode: 1.4.1 + dev: true + + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.1.0 + dev: true + + /trim-right@1.0.1: + resolution: {integrity: sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==} + engines: {node: '>=0.10.0'} + dev: true + + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.1.1 + dev: true + + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: true + optional: true + + /type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.1.2 + dev: true + + /uglify-js@2.8.29: + resolution: {integrity: sha512-qLq/4y2pjcU3vhlhseXGGJ7VbFO4pBANu0kwl8VCa9KEI0V8VfZIx2Fy3w01iSTA/pGwKZSmu/+I4etLNDdt5w==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dependencies: + source-map: 0.5.7 + yargs: 3.10.0 + optionalDependencies: + uglify-to-browserify: 1.0.2 + dev: true + optional: true + + /uglify-to-browserify@1.0.2: + resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + requiresBuild: true + dev: true + optional: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /util.promisify@1.0.0: + resolution: {integrity: sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==} + dependencies: + define-properties: 1.1.2 + object.getownpropertydescriptors: 2.0.3 + dev: true + + /uuid@3.1.0: + resolution: {integrity: sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: true + + /validate-npm-package-license@3.0.1: + resolution: {integrity: sha512-VD0zBfAttoSxzPa+I+rF6ckOEEPSbifYNTSgRW5BsyfaD7gSE/uge00r2Xqa0d/yhF1MyHnMPHqLUdQRNimR2A==} + dependencies: + spdx-correct: 1.0.2 + spdx-expression-parse: 1.0.4 + dev: true + + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: true + + /walker@1.0.7: + resolution: {integrity: sha512-cF4je9Fgt6sj1PKfuFt9jpQPeHosM+Ryma/hfY9U7uXGKM7pJCsF0v2r55o+Il54+i77SyYWetB4tD1dEygRkw==} + dependencies: + makeerror: 1.0.11 + dev: true + + /watch@0.18.0: + resolution: {integrity: sha512-oUcoHFG3UF2pBlHcMORAojsN09BfqSfWYWlR3eSSjUFR7eBEx53WT2HX/vZeVTTIVCGShcazb+t6IcBRCNXqvA==} + engines: {node: '>=0.1.95'} + hasBin: true + dependencies: + exec-sh: 0.2.0 + minimist: 1.2.0 + dev: true + + /weak@1.0.1: + resolution: {integrity: sha512-wlbyWH3+bgtLHO0ekeAdvCYKRQJNF7sl7bKESG7PW+p5CgfEay1ChkK/d7nRXFTPvhdddwVAeXCfmxkNH3YICQ==} + requiresBuild: true + dependencies: + bindings: 1.3.0 + nan: 2.8.0 + dev: true + optional: true + + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /whatwg-encoding@1.0.1: + resolution: {integrity: sha512-vNmnbXn9p8aTkdOFh5lVbEyT1xXFFCDvrGIJyAnKdWYU1F4HN/4OgP7j3QVl4EIk7bhMg6pIopJexnKeWCisxg==} + dependencies: + iconv-lite: 0.4.13 + dev: true + + /whatwg-fetch@2.0.3: + resolution: {integrity: sha512-SA2KdOXATOroD3EBUYvcdugsusXS5YiQFqwskSbsp5b1gK8HpNi/YP0jcy/BDpdllp305HMnrsVf9K7Be9GiEQ==} + dev: false + + /whatwg-url@6.4.0: + resolution: {integrity: sha512-Z0CVh/YE217Foyb488eo+iBv+r7eAQ0wSTyApi9n06jhcA3z6Nidg/EGvl0UFkg7kMdKxfBzzr+o9JF+cevgMg==} + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + dev: true + + /which-module@2.0.0: + resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} + dev: true + + /which@1.3.0: + resolution: {integrity: sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /window-size@0.1.0: + resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} + engines: {node: '>= 0.8.0'} + dev: true + optional: true + + /wordwrap@0.0.2: + resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} + engines: {node: '>=0.4.0'} + dev: true + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + + /wrap-ansi@2.1.0: + resolution: {integrity: sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==} + engines: {node: '>=0.10.0'} + dependencies: + string-width: 1.0.2 + strip-ansi: 3.0.1 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@2.3.0: + resolution: {integrity: sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==} + dependencies: + graceful-fs: 4.1.11 + imurmurhash: 0.1.4 + signal-exit: 3.0.2 + dev: true + + /xml-name-validator@2.0.1: + resolution: {integrity: sha512-jRKe/iQYMyVJpzPH+3HL97Lgu5HrCfii+qSo+TfjKHtOnvbnvdVfMYrn9Q34YV81M2e5sviJlI6Ko9y+nByzvA==} + dev: true + + /y18n@3.2.1: + resolution: {integrity: sha512-Vd1yWKYGMtzFB6bAuTI7/POwJnwQStQXOe1PW1GmjUZgkaKYGc6/Pl3IDGFgplEklF65niuwBHeS5yve4+U01Q==} + dev: true + + /yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + dev: true + + /yargs-parser@8.1.0: + resolution: {integrity: sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==} + dependencies: + camelcase: 4.1.0 + dev: true + + /yargs@10.0.3: + resolution: {integrity: sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==} + dependencies: + cliui: 3.2.0 + decamelize: 1.2.0 + find-up: 2.1.0 + get-caller-file: 1.0.2 + os-locale: 2.1.0 + require-directory: 2.1.1 + require-main-filename: 1.0.1 + set-blocking: 2.0.0 + string-width: 2.1.1 + which-module: 2.0.0 + y18n: 3.2.1 + yargs-parser: 8.1.0 + dev: true + + /yargs@3.10.0: + resolution: {integrity: sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==} + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: true + optional: true diff --git a/nub/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml b/nub/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml new file mode 100644 index 00000000000..a78b5175ff4 --- /dev/null +++ b/nub/helpers/test/pnpm/fixtures/parser/only_dev_dependencies/pnpm-lock.yaml @@ -0,0 +1,16 @@ +lockfileVersion: 5.4 + +specifiers: + etag: ^1.0.0 + +devDependencies: + etag: + specifier: ^1.0.0 + version: 1.8.0 + +packages: + + /etag@1.8.0: + resolution: { integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== } + engines: { node: '>= 0.6' } + dev: true diff --git a/nub/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml b/nub/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml new file mode 100644 index 00000000000..6971d722e2a --- /dev/null +++ b/nub/helpers/test/pnpm/fixtures/parser/peer_disambiguation/pnpm-lock.yaml @@ -0,0 +1,855 @@ +lockfileVersion: 5.4 + +specifiers: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^8.26.0 + typescript: 4.9.5 + +devDependencies: + '@typescript-eslint/parser': + specifier: ^5.0.0 + version: 5.59.0 + eslint: + specifier: ^8.26.0 + version: 8.38.0 + typescript: + specifier: 4.9.5 + version: 4.9.5 + +packages: + + /@eslint-community/eslint-utils/4.4.0_eslint@8.38.0: + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.38.0 + eslint-visitor-keys: 3.4.0 + dev: true + + /@eslint-community/regexpp@4.5.0: + resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.0.2: + resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.5.1 + globals: 13.20.0 + ignore: 5.2.4 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.38.0: + resolution: {integrity: sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.8: + resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@1.2.1: + resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@typescript-eslint/parser@5.59.0: + resolution: {integrity: sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/typescript-estree': 5.59.0_typescript@4.9.5 + debug: 4.3.4 + eslint: 8.38.0 + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@5.59.0: + resolution: {integrity: sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/visitor-keys': 5.59.0 + dev: true + + /@typescript-eslint/types@5.59.0: + resolution: {integrity: sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@typescript-eslint/typescript-estree/5.59.0_typescript@4.9.5: + resolution: {integrity: sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/visitor-keys': 5.59.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.5.0 + tsutils: 3.21.0_typescript@4.9.5 + typescript: 4.9.5 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/visitor-keys@5.59.0: + resolution: {integrity: sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.59.0 + eslint-visitor-keys: 3.4.0 + dev: true + + /acorn-jsx/5.3.2_acorn@8.8.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.8.2 + dev: true + + /acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-scope@7.2.0: + resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.38.0: + resolution: {integrity: sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0_eslint@8.38.0 + '@eslint-community/regexpp': 4.5.0 + '@eslint/eslintrc': 2.0.2 + '@eslint/js': 8.38.0 + '@humanwhocodes/config-array': 0.11.8 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.0 + espree: 9.5.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.20.0 + grapheme-splitter: 1.0.4 + ignore: 5.2.4 + import-fresh: 3.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-sdsl: 4.4.0 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.1 + strip-ansi: 6.0.1 + strip-json-comments: 3.1.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.5.1: + resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.8.2 + acorn-jsx: 5.3.2_acorn@8.8.2 + eslint-visitor-keys: 3.4.0 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.2.12: + resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.0.4: + resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.7 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.7: + resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@13.20.0: + resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.12 + ignore: 5.2.4 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /grapheme-splitter@1.0.4: + resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /ignore@5.2.4: + resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /js-sdsl@4.4.0: + resolution: {integrity: sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.1: + resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} + engines: {node: '>= 0.8.0'} + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.3 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /semver@7.5.0: + resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: true + + /tsutils/3.21.0_typescript@4.9.5: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 4.9.5 + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typescript@4.9.5: + resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /word-wrap@1.2.3: + resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + engines: {node: '>=0.10.0'} + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/nub/helpers/test/pnpm/lockfile-parser.test.js b/nub/helpers/test/pnpm/lockfile-parser.test.js new file mode 100644 index 00000000000..d567289b6c1 --- /dev/null +++ b/nub/helpers/test/pnpm/lockfile-parser.test.js @@ -0,0 +1,79 @@ +const { + parseLockfile, +} = require("../../lib/pnpm"); +const fs = require("fs"); +const os = require("os"); +const path = require("path"); + +describe("generates an updated pnpm lock for the original file", () => { + + let tempDir; + beforeEach(() => { + tempDir = fs.mkdtempSync(os.tmpdir() + path.sep); + }); + afterEach(() => fs.rm(tempDir, { recursive: true }, () => {})); + + function copyDependencies(sourceDir, destDir) { + const srcPnpmYaml = path.join( + __dirname, + `fixtures/parser/${sourceDir}/pnpm-lock.yaml` + ); + fs.copyFileSync(srcPnpmYaml, `${destDir}/pnpm-lock.yaml`); + } + + it("that contains duplicate dependencies", async () =>{ + copyDependencies("no_lockfile_change", tempDir); + const result = await parseLockfile(tempDir); + + expect(result.length).toEqual(398); + }) + + it("that contains only dev dependencies but no (prod) dependencies", async () =>{ + copyDependencies("only_dev_dependencies", tempDir); + const result = await parseLockfile(tempDir); + + expect(result).toEqual([ + { + name: 'etag', + version: '1.8.0', + resolved: undefined, + dev: true, + specifiers: [ '^1.0.0' ], + aliased: false + } + ]); + }) + + it("that contains dependencies which locked to versions with peer disambiguation suffix", async () =>{ + copyDependencies("peer_disambiguation", tempDir); + const result = await parseLockfile(tempDir); + + expect(result.length).toEqual(122); + }) + + // Should have the version in the lock file. + it("that contains dependencies with an empty version", async () =>{ + copyDependencies("empty_version", tempDir); + const result = await parseLockfile(tempDir); + + expect(result.length).toEqual(9); + }) + + // pnpm v9+ lockfiles don't have resolution.tarball for npm packages + it("that uses lockfileVersion 9.0 format without resolution.tarball", async () =>{ + copyDependencies("lockfile_v9", tempDir); + const result = await parseLockfile(tempDir); + + expect(result).toEqual([ + { + name: 'etag', + version: '1.8.1', + resolved: undefined, + dev: undefined, + specifiers: [ '^1.0.0' ], + aliased: false + } + ]); + }) + +}) diff --git a/nub/lib/dependabot/nub.rb b/nub/lib/dependabot/nub.rb new file mode 100644 index 00000000000..05e89246082 --- /dev/null +++ b/nub/lib/dependabot/nub.rb @@ -0,0 +1,27 @@ +# typed: strict +# frozen_string_literal: true + +# These all need to be required so the various classes can be registered in a +# lookup table of package manager names to concrete classes. +require "dependabot/nub/file_fetcher" +require "dependabot/nub/file_parser" +require "dependabot/nub/update_checker" +require "dependabot/nub/file_updater" +require "dependabot/nub/metadata_finder" +require "dependabot/nub/requirement" +require "dependabot/nub/version" + +require "dependabot/pull_request_creator/labeler" +Dependabot::PullRequestCreator::Labeler + .register_label_details("nub", name: "javascript", colour: "168700") + +require "dependabot/dependency" +Dependabot::Dependency.register_production_check( + "nub", + lambda do |groups| + return true if groups.empty? + return true if groups.include?("optionalDependencies") + + groups.include?("dependencies") + end +) diff --git a/nub/lib/dependabot/nub/constraint_helper.rb b/nub/lib/dependabot/nub/constraint_helper.rb new file mode 100644 index 00000000000..d9621304f7b --- /dev/null +++ b/nub/lib/dependabot/nub/constraint_helper.rb @@ -0,0 +1,362 @@ +# typed: strict +# frozen_string_literal: true + +require "sorbet-runtime" + +module Dependabot + module Nub + module ConstraintHelper + extend T::Sig + + # Regex Components for Semantic Versioning + DIGIT = "\\d+" # Matches a single number (e.g., "1") + PRERELEASE = "(?:-[a-zA-Z0-9.-]+)?" # Matches optional pre-release tag (e.g., "-alpha") + BUILD_METADATA = "(?:\\+[a-zA-Z0-9.-]+)?" # Matches optional build metadata (e.g., "+001") + + # Matches semantic versions: + VERSION = T.let("#{DIGIT}(?:\\.#{DIGIT}){0,2}#{PRERELEASE}#{BUILD_METADATA}".freeze, String) + + VERSION_REGEX = /^#{VERSION}$/ + + # Base regex for SemVer (major.minor.patch[-prerelease][+build]) + # This pattern extracts valid semantic versioning strings based on the SemVer 2.0 specification. + SEMVER_REGEX = / + (?\d+\.\d+\.\d+) # Match major.minor.patch (e.g., 1.2.3) + (?:-(?[a-zA-Z0-9.-]+))? # Optional prerelease (e.g., -alpha.1, -rc.1, -beta.5) + (?:\+(?[a-zA-Z0-9.-]+))? # Optional build metadata (e.g., +build.20231101, +exp.sha.5114f85) + /x + + # Full SemVer validation regex (ensures the entire string is a valid SemVer) + # This ensures the entire input strictly follows SemVer, without extra characters before/after. + SEMVER_VALIDATION_REGEX = /^#{SEMVER_REGEX}$/ + + # SemVer constraint regex (supports package.json version constraints) + # This pattern ensures proper parsing of SemVer versions with optional operators. + SEMVER_CONSTRAINT_REGEX = / + (?: (>=|<=|>|<|=|~|\^)\s*)? # Make operators optional (e.g., >=, ^, ~) + (\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?(?:\+[a-zA-Z0-9.-]+)?) # Match full SemVer versions + | (\*|latest) # Match wildcard (*) or 'latest' + /x + + # /(>=|<=|>|<|=|~|\^)\s*(\d+\.\d+\.\d+(?:-[a-zA-Z0-9.-]+)?(?:\+[a-zA-Z0-9.-]+)?)|(\*|latest)/ + + SEMVER_OPERATOR_REGEX = /^(>=|<=|>|<|~|\^|=)$/ + + # Constraint Types as Constants + CARET_CONSTRAINT_REGEX = /^\^\s*(#{VERSION})$/ + TILDE_CONSTRAINT_REGEX = /^~\s*(#{VERSION})$/ + EXACT_CONSTRAINT_REGEX = /^\s*(#{VERSION})$/ + GREATER_THAN_EQUAL_REGEX = /^>=\s*(#{VERSION})$/ + LESS_THAN_EQUAL_REGEX = /^<=\s*(#{VERSION})$/ + GREATER_THAN_REGEX = /^>\s*(#{VERSION})$/ + LESS_THAN_REGEX = /^<\s*(#{VERSION})$/ + WILDCARD_REGEX = /^\*$/ + LATEST_REGEX = /^latest$/ + SEMVER_CONSTANTS = ["*", "latest"].freeze + + # Unified Regex for Valid Constraints + VALID_CONSTRAINT_REGEX = T.let( + Regexp.union( + CARET_CONSTRAINT_REGEX, + TILDE_CONSTRAINT_REGEX, + EXACT_CONSTRAINT_REGEX, + GREATER_THAN_EQUAL_REGEX, + LESS_THAN_EQUAL_REGEX, + GREATER_THAN_REGEX, + LESS_THAN_REGEX, + WILDCARD_REGEX, + LATEST_REGEX + ).freeze, + Regexp + ) + + # Extract unique constraints from the given constraint expression. + # @param constraint_expression [T.nilable(String)] The semver constraint expression. + # @return [T::Array[String]] The list of unique Ruby-compatible constraints. + sig do + params( + constraint_expression: T.nilable(String), + dependabot_versions: T.nilable(T::Array[Dependabot::Version]) + ) + .returns(T.nilable(T::Array[String])) + end + def self.extract_ruby_constraints(constraint_expression, dependabot_versions = nil) + parsed_constraints = parse_constraints(constraint_expression, dependabot_versions) + + return nil unless parsed_constraints + + parsed_constraints.filter_map { |parsed| parsed[:constraint] } + end + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/PerceivedComplexity + sig do + params(constraint_expression: T.nilable(String)) + .returns(T.nilable(T::Array[String])) + end + def self.split_constraints(constraint_expression) + normalized_constraint = constraint_expression&.strip + return [] if normalized_constraint.nil? || normalized_constraint.empty? + + # Split constraints by logical OR (`||`) + constraint_groups = normalized_constraint.split("||") + + # Split constraints by logical AND (`,`) + constraint_groups = constraint_groups.map do |or_constraint| + or_constraint.split(",").map(&:strip) + end.flatten + + constraint_groups = constraint_groups.map do |constraint| + tokens = constraint.split(/\s+/).map(&:strip) + + and_constraints = [] + + previous = T.let(nil, T.nilable(String)) + operator = T.let(false, T.nilable(T::Boolean)) + wildcard = T.let(false, T::Boolean) + + tokens.each do |token| + token = token.strip + next if token.empty? + + # Invalid constraint if wildcard and anything else + return nil if wildcard + + # If token is one of the operators (>=, <=, >, <, ~, ^, =) + if token.match?(SEMVER_OPERATOR_REGEX) + wildcard = false + operator = true + # If token is wildcard or latest + elsif token.match?(/(\*|latest)/) + and_constraints << token + wildcard = true + operator = false + # If token is exact version (e.g., "1.2.3") + elsif token.match(VERSION_REGEX) + and_constraints << if operator + "#{previous}#{token}" + else + token + end + wildcard = false + operator = false + # If token is a valid constraint (e.g., ">=1.2.3", "<=2.0.0") + elsif token.match(VALID_CONSTRAINT_REGEX) + return nil if operator + + and_constraints << token + + wildcard = false + operator = false + else + # invalid constraint + return nil + end + previous = token + end + and_constraints.uniq + end.flatten + constraint_groups if constraint_groups.any? + end + + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/PerceivedComplexity + + # Find the highest version from the given constraint expression. + # @param constraint_expression [T.nilable(String)] The semver constraint expression. + # @return [T.nilable(String)] The highest version, or nil if no versions are available. + sig do + params( + constraint_expression: T.nilable(String), + dependabot_versions: T.nilable(T::Array[Dependabot::Version]) + ) + .returns(T.nilable(String)) + end + def self.find_highest_version_from_constraint_expression(constraint_expression, dependabot_versions = nil) + parsed_constraints = parse_constraints(constraint_expression, dependabot_versions) + + return nil unless parsed_constraints + + parsed_constraints + .filter_map { |parsed| parsed[:version] } # Extract all versions + .max_by { |version| Version.new(version) } + end + + # Parse all constraints (split by logical OR `||`) and convert to Ruby-compatible constraints. + # Return: + # - `nil` if the constraint expression is invalid + # - `[]` if the constraint expression is valid but represents "no constraints" + # - An array of hashes for valid constraints with details about the constraint and version + sig do + params( + constraint_expression: T.nilable(String), + dependabot_versions: T.nilable(T::Array[Dependabot::Version]) + ) + .returns(T.nilable(T::Array[T::Hash[Symbol, T.nilable(String)]])) + end + def self.parse_constraints(constraint_expression, dependabot_versions = nil) + splitted_constraints = split_constraints(constraint_expression) + + return unless splitted_constraints + + constraints = to_ruby_constraints_with_versions(splitted_constraints, dependabot_versions) + constraints + end + + sig do + params( + constraints: T::Array[String], + dependabot_versions: T.nilable(T::Array[Dependabot::Version]) + ).returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) + end + def self.to_ruby_constraints_with_versions(constraints, dependabot_versions = []) + constraints.filter_map do |constraint| + parsed = to_ruby_constraint_with_version(constraint, dependabot_versions) + parsed if parsed + end.uniq + end + + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity + # Converts a semver constraint to a Ruby-compatible constraint and extracts the version, if available. + # @param constraint [String] The semver constraint to parse. + # @return [T.nilable(T::Hash[Symbol, T.nilable(String)])] Returns the Ruby-compatible constraint and the version, + # if available, or nil if the constraint is invalid. + # + # @example + # to_ruby_constraint_with_version("=1.2.3") # => { constraint: "=1.2.3", version: "1.2.3" } + # to_ruby_constraint_with_version("^1.2.3") # => { constraint: ">=1.2.3 <2.0.0", version: "1.2.3" } + # to_ruby_constraint_with_version("*") # => { constraint: nil, version: nil } + # to_ruby_constraint_with_version("invalid") # => nil + sig do + params( + constraint: String, + dependabot_versions: T.nilable(T::Array[Dependabot::Version]) + ) + .returns(T.nilable(T::Hash[Symbol, T.nilable(String)])) + end + def self.to_ruby_constraint_with_version(constraint, dependabot_versions = []) + return nil if constraint.empty? + + case constraint + when EXACT_CONSTRAINT_REGEX # Exact version, e.g., "1.2.3-alpha" + return unless Regexp.last_match + + full_version = Regexp.last_match(1) + { constraint: "=#{full_version}", version: full_version } + when CARET_CONSTRAINT_REGEX # Caret constraint, e.g., "^1.2.3" + return unless Regexp.last_match + + full_version = Regexp.last_match(1) + _, major, minor = version_components(full_version) + return nil if major.nil? + + ruby_constraint = + if major.to_i.zero? + minor.nil? ? ">=#{full_version} <1.0.0" : ">=#{full_version} <0.#{minor.to_i + 1}.0" + else + ">=#{full_version} <#{major.to_i + 1}.0.0" + end + { constraint: ruby_constraint, version: full_version } + when TILDE_CONSTRAINT_REGEX # Tilde constraint, e.g., "~1.2.3" + return unless Regexp.last_match + + full_version = Regexp.last_match(1) + _, major, minor = version_components(full_version) + ruby_constraint = + if minor.nil? + ">=#{full_version} <#{major.to_i + 1}.0.0" + else + ">=#{full_version} <#{major}.#{minor.to_i + 1}.0" + end + { constraint: ruby_constraint, version: full_version } + when GREATER_THAN_EQUAL_REGEX # Greater than or equal, e.g., ">=1.2.3" + + return unless Regexp.last_match && Regexp.last_match(1) + + found_version = highest_matching_version( + dependabot_versions, + T.must(Regexp.last_match(1)) + ) do |version, constraint_version| + version >= Version.new(constraint_version) + end + { constraint: ">=#{Regexp.last_match(1)}", version: found_version&.to_s } + when LESS_THAN_EQUAL_REGEX # Less than or equal, e.g., "<=1.2.3" + return unless Regexp.last_match + + full_version = Regexp.last_match(1) + { constraint: "<=#{full_version}", version: full_version } + when GREATER_THAN_REGEX # Greater than, e.g., ">1.2.3" + return unless Regexp.last_match && Regexp.last_match(1) + + found_version = highest_matching_version( + dependabot_versions, + T.must(Regexp.last_match(1)) + ) do |version, constraint_version| + version > Version.new(constraint_version) + end + { constraint: ">#{Regexp.last_match(1)}", version: found_version&.to_s } + when LESS_THAN_REGEX # Less than, e.g., "<1.2.3" + return unless Regexp.last_match && Regexp.last_match(1) + + found_version = highest_matching_version( + dependabot_versions, + T.must(Regexp.last_match(1)) + ) do |version, constraint_version| + version < Version.new(constraint_version) + end + { constraint: "<#{Regexp.last_match(1)}", version: found_version&.to_s } + when WILDCARD_REGEX # No specific constraint, resolves to the highest available version + { constraint: nil, version: dependabot_versions&.max&.to_s } + when LATEST_REGEX + { constraint: nil, version: dependabot_versions&.max&.to_s } # Resolves to the latest available version + end + end + + sig do + params( + dependabot_versions: T.nilable(T::Array[Dependabot::Version]), + constraint_version: String, + condition: T.proc.params(version: Dependabot::Version, constraint: Dependabot::Version).returns(T::Boolean) + ) + .returns(T.nilable(Dependabot::Version)) + end + def self.highest_matching_version(dependabot_versions, constraint_version, &condition) + return unless dependabot_versions&.any? + + # Returns the highest version that satisfies the condition, or nil if none. + dependabot_versions + .sort + .reverse + .find { |version| condition.call(version, Version.new(constraint_version)) } # rubocop:disable Performance/RedundantBlockCall + end + + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + + # Parses a semantic version string into its components as per the SemVer spec + # Example: "1.2.3-alpha+001" → ["1.2.3", "1", "2", "3", "alpha", "001"] + sig { params(full_version: T.nilable(String)).returns(T.nilable(T::Array[String])) } + def self.version_components(full_version) + return [] if full_version.nil? + + match = full_version.match(SEMVER_VALIDATION_REGEX) + return [] unless match + + version = match[:version] + return [] unless version + + major, minor, patch = version.split(".") + [version, major, minor, patch, match[:prerelease], match[:build]].compact + end + end + end +end diff --git a/nub/lib/dependabot/nub/dependency_files_filterer.rb b/nub/lib/dependabot/nub/dependency_files_filterer.rb new file mode 100644 index 00000000000..be898799ea1 --- /dev/null +++ b/nub/lib/dependabot/nub/dependency_files_filterer.rb @@ -0,0 +1,163 @@ +# typed: strict +# frozen_string_literal: true + +require "dependabot/utils" +require "dependabot/nub/file_parser/lockfile_parser" +require "sorbet-runtime" + +# Used in the version resolver and file updater to only run yarn/npm helpers on +# dependency files that require updates. This is useful for large monorepos with +# lots of sub-projects that don't all have the same dependencies. +module Dependabot + module Nub + class DependencyFilesFilterer + extend T::Sig + + sig { params(dependency_files: T::Array[DependencyFile], updated_dependencies: T::Array[Dependency]).void } + def initialize(dependency_files:, updated_dependencies:) + @dependency_files = dependency_files + @updated_dependencies = updated_dependencies + end + + sig { returns(T::Array[String]) } + def paths_requiring_update_check + @paths_requiring_update_check ||= T.let(fetch_paths_requiring_update_check, T.nilable(T::Array[String])) + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def files_requiring_update + @files_requiring_update ||= T.let( + dependency_files.select do |file| + package_files_requiring_update.include?(file) || + package_required_lockfile?(file) || + workspaces_lockfile?(file) + end, + T.nilable(T::Array[DependencyFile]) + ) + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def package_files_requiring_update + @package_files_requiring_update ||= T.let( + dependency_files.select do |file| + dependency_manifest_requirements.include?(file.name) + end, + T.nilable(T::Array[DependencyFile]) + ) + end + + private + + sig { returns(T::Array[DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependency]) } + attr_reader :updated_dependencies + + sig { returns(T::Array[String]) } + def fetch_paths_requiring_update_check + # if only a root lockfile exists, it tracks all dependencies + return [File.dirname(T.must(root_lockfile).name)] if lockfiles == [root_lockfile] + + package_files_requiring_update.map do |file| + File.dirname(file.name) + end + end + + sig { returns(T::Array[String]) } + def dependency_manifest_requirements + @dependency_manifest_requirements ||= T.let( + updated_dependencies.flat_map do |dep| + dep.requirements.filter_map(&:file) + end, + T.nilable(T::Array[String]) + ) + end + + sig { params(lockfile: DependencyFile).returns(T::Boolean) } + def package_required_lockfile?(lockfile) + return false unless lockfile?(lockfile) + + package_files_requiring_update.any? do |package_file| + File.dirname(package_file.name) == File.dirname(lockfile.name) + end + end + + sig { params(lockfile: DependencyFile).returns(T::Boolean) } + def workspaces_lockfile?(lockfile) + return false unless ["yarn.lock", "package-lock.json", "pnpm-lock.yaml", "nub.lock"].include?(lockfile.name) + + return false unless parsed_root_package_json["workspaces"] || dependency_files.any? do |file| + file.name.end_with?("pnpm-workspace.yaml") && File.dirname(file.name) == File.dirname(lockfile.name) + end + + updated_dependencies_in_lockfile?(lockfile) + end + + sig { returns(T.nilable(DependencyFile)) } + def root_lockfile + @root_lockfile ||= T.let( + lockfiles.find do |file| + File.dirname(file.name) == "." + end, + T.nilable(DependencyFile) + ) + end + + sig { returns(T::Array[DependencyFile]) } + def lockfiles + @lockfiles ||= T.let( + dependency_files.select do |file| + lockfile?(file) + end, + T.nilable(T::Array[DependencyFile]) + ) + end + + sig { returns(T::Hash[String, T.untyped]) } + def parsed_root_package_json + @parsed_root_package_json ||= T.let( + begin + package = T.must(dependency_files.find { |f| f.name == "package.json" }) + JSON.parse(T.must(package.content)) + end, + T.nilable(T::Hash[String, T.untyped]) + ) + end + + sig { params(lockfile: Dependabot::DependencyFile).returns(T::Boolean) } + def updated_dependencies_in_lockfile?(lockfile) + lockfile_dependencies(lockfile).any? do |sub_dep| + updated_dependencies.any? do |updated_dep| + sub_dep.name == updated_dep.name + end + end + end + + sig { params(lockfile: DependencyFile).returns(T::Array[Dependency]) } + def lockfile_dependencies(lockfile) + @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]])) + @lockfile_dependencies[lockfile.name] ||= + Nub::FileParser::LockfileParser.new( + dependency_files: [lockfile] + ).parse + end + + sig { params(file: DependencyFile).returns(T::Boolean) } + def manifest?(file) + file.name.end_with?("package.json") + end + + sig { params(file: DependencyFile).returns(T::Boolean) } + def lockfile?(file) + file.name.end_with?( + "package-lock.json", + "yarn.lock", + "pnpm-lock.yaml", + "nub.lock", + "npm-shrinkwrap.json" + ) + end + end + end +end diff --git a/nub/lib/dependabot/nub/file_fetcher.rb b/nub/lib/dependabot/nub/file_fetcher.rb new file mode 100644 index 00000000000..d8568a9b6b6 --- /dev/null +++ b/nub/lib/dependabot/nub/file_fetcher.rb @@ -0,0 +1,398 @@ +# typed: strict +# frozen_string_literal: true + +require "json" +require "sorbet-runtime" +require "dependabot/experiments" +require "dependabot/logger" +require "dependabot/file_fetchers" +require "dependabot/file_fetchers/base" +require "dependabot/nub/helpers" +require "dependabot/nub/package_manager" +require "dependabot/nub/file_parser" +require "dependabot/nub/file_parser/lockfile_parser" +require "dependabot/file_filtering" + +module Dependabot + module Nub + class FileFetcher < Dependabot::FileFetchers::Base + extend T::Sig + extend T::Helpers + + # Npm always prefixes file paths in the lockfile "version" with "file:" + # even when a naked path is used (e.g. "../dep") + NPM_PATH_DEPENDENCY_STARTS = T.let(%w(file:).freeze, [String]) + # "link:" is only supported by Yarn but is interchangeable with "file:" + # when it specifies a path. Only include Yarn "link:"'s that start with a + # path and ignore symlinked package names that have been registered with + # "yarn link", e.g. "link:react" + PATH_DEPENDENCY_STARTS = T.let( + %w(file: link:. link:/ link:~/ / ./ ../ ~/).freeze, + [String, String, String, String, String, String, String, String] + ) + PATH_DEPENDENCY_CLEAN_REGEX = /^file:|^link:/ + DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org" + + sig { override.params(filenames: T::Array[String]).returns(T::Boolean) } + def self.required_files_in?(filenames) + filenames.include?("package.json") + end + + sig { override.returns(String) } + def self.required_files_message + "Repo must contain a package.json." + end + + sig { override.returns(T.nilable(T::Hash[Symbol, T.untyped])) } + def ecosystem_versions + package_managers = {} + + package_managers["nub"] = nub_version if nub_version + package_managers["unknown"] = 1 if package_managers.empty? + + { + package_managers: package_managers + } + end + + sig { override.returns(T::Array[DependencyFile]) } + def fetch_files + fetched_files = T.let([], T::Array[DependencyFile]) + fetched_files << package_json + fetched_files << T.must(npmrc) if npmrc + fetched_files += nub_files if nub_version + fetched_files += workspace_package_jsons + fetched_files += path_dependencies(fetched_files) + + # Filter excluded files from final collection + filtered_files = fetched_files.uniq.reject do |file| + Dependabot::FileFiltering.should_exclude_path?(file.name, "file from final collection", @exclude_paths) + end + + filtered_files + end + + private + + sig { returns(T::Array[DependencyFile]) } + def nub_files + fetched_nub_files = [] + fetched_nub_files << nub_lock if nub_lock + fetched_nub_files + end + + # If every entry in the lockfile uses the same registry, we can infer + # that there is a global .npmrc file, so add it here as if it were in the repo. + + sig { returns(T.nilable(T.any(Integer, String))) } + def nub_version + @nub_version ||= T.let( + package_manager_helper.setup(NubPackageManager::NAME), + T.nilable(T.any(Integer, String)) + ) + end + + sig { returns(PackageManagerHelper) } + def package_manager_helper + @package_manager_helper ||= T.let( + PackageManagerHelper.new( + parsed_package_json, + lockfiles, + registry_config_files, + credentials + ), + T.nilable(PackageManagerHelper) + ) + end + + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def lockfiles + { + nub: nub_lock + } + end + + # Returns the .npmrc, and .yarnrc files for the repository. + # @return [Hash{Symbol => Dependabot::DependencyFile}] + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def registry_config_files + { + npmrc: npmrc + } + end + + sig { returns(DependencyFile) } + def package_json + @package_json ||= T.let(fetch_file_from_host(MANIFEST_FILENAME), T.nilable(DependencyFile)) + end + + sig { returns(T.nilable(DependencyFile)) } + def nub_lock + return @nub_lock if defined?(@nub_lock) + + @nub_lock ||= T.let(fetch_file_if_present(NubPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile)) + + return @nub_lock if @nub_lock || directory == "/" + + @nub_lock = fetch_file_from_parent_directories(NubPackageManager::LOCKFILE_NAME) + end + + sig { returns(T.nilable(DependencyFile)) } + def npmrc + return @npmrc if defined?(@npmrc) + + @npmrc ||= T.let(fetch_support_file(NubPackageManager::RC_FILENAME), T.nilable(DependencyFile)) + + return @npmrc if @npmrc || directory == "/" + + @npmrc = fetch_file_from_parent_directories(NubPackageManager::RC_FILENAME) + end + + sig { returns(T::Array[DependencyFile]) } + def workspace_package_jsons + @workspace_package_jsons ||= T.let(fetch_workspace_package_jsons, T.nilable(T::Array[DependencyFile])) + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { params(fetched_files: T::Array[DependencyFile]).returns(T::Array[DependencyFile]) } + def path_dependencies(fetched_files) + package_json_files = T.let([], T::Array[DependencyFile]) + unfetchable_deps = T.let([], T::Array[[String, String]]) + + path_dependency_details(fetched_files).each do |name, path| + # This happens with relative paths in the package-lock. Skipping it since it results + # in /package.json which is outside of the project directory. + next if path == "file:" + + path = path.gsub(PATH_DEPENDENCY_CLEAN_REGEX, "") + raise PathDependenciesNotReachable, "#{name} at #{path}" if path.start_with?("/") + + filename = path + # NPM/Yarn support loading path dependencies from tarballs: + # https://docs.npmjs.com/cli/pack.html + filename = File.join(filename, MANIFEST_FILENAME) unless filename.end_with?(".tgz", ".tar", ".tar.gz") + cleaned_name = Pathname.new(filename).cleanpath.to_path + next if fetched_files.map(&:name).include?(cleaned_name) + + # Skip excluded path dependencies + next if Dependabot::FileFiltering.should_exclude_path?(cleaned_name, "path dependency file", @exclude_paths) + + begin + file = fetch_file_from_host(filename, fetch_submodules: true) + package_json_files << file + rescue Dependabot::DependencyFileNotFound + # Unfetchable tarballs should not be re-fetched as a package + unfetchable_deps << [name, path] unless path.end_with?(".tgz", ".tar", ".tar.gz") + end + end + + if package_json_files.any? + package_json_files += + path_dependencies(fetched_files + package_json_files) + end + + package_json_files.tap { |fs| fs.each { |f| f.support_file = true } } + end + # rubocop:enable Metrics/PerceivedComplexity + + sig { params(fetched_files: T::Array[DependencyFile]).returns(T::Array[[String, String]]) } + def path_dependency_details(fetched_files) + package_json_path_deps = T.let([], T::Array[[String, String]]) + + fetched_files.each do |file| + package_json_path_deps += + path_dependency_details_from_manifest(file) + end + + [*package_json_path_deps].uniq + end + + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/AbcSize + sig { params(file: DependencyFile).returns(T::Array[[String, String]]) } + def path_dependency_details_from_manifest(file) + return [] unless file.name.end_with?(MANIFEST_FILENAME) + + current_dir = file.name.rpartition("/").first + current_dir = nil if current_dir == "" + + current_depth = File.join(directory, file.name).split("/").count { |path| !path.empty? } + path_to_directory = "../" * current_depth + + dep_types = FileParser::DEPENDENCY_TYPES + parsed_manifest = JSON.parse(T.must(file.content)) + dependency_objects = parsed_manifest.values_at(*dep_types).compact + # Fetch yarn "file:" path "resolutions" so the lockfile can be resolved + resolution_objects = parsed_manifest.values_at("resolutions").compact + manifest_objects = dependency_objects + resolution_objects + + raise Dependabot::DependencyFileNotParseable, file.path unless manifest_objects.all?(Hash) + + resolution_deps = resolution_objects.flat_map(&:to_a) + .map do |path, value| + # skip dependencies that contain invalid values + # such as inline comments, null, etc. + + unless value.is_a?(String) + Dependabot.logger.warn( + "File fetcher: Skipping dependency \"#{path}\" " \ + "with value: \"#{value}\"" + ) + + next + end + + convert_dependency_path_to_name(path, value) + end + + path_starts = PATH_DEPENDENCY_STARTS + (dependency_objects.flat_map(&:to_a) + resolution_deps) + .select { |_, v| v.is_a?(String) && v.start_with?(*path_starts) } + .map do |name, path| + path = path.gsub(PATH_DEPENDENCY_CLEAN_REGEX, "") + raise PathDependenciesNotReachable, "#{name} at #{path}" if path.start_with?("/", "#{path_to_directory}..") + + path = File.join(current_dir, path) unless current_dir.nil? + [name, Pathname.new(path).cleanpath.to_path] + end + rescue JSON::ParserError + raise Dependabot::DependencyFileNotParseable, file.path + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/PerceivedComplexity + + sig { params(parsed_lockfile: T.untyped).returns(T::Array[[String, String]]) } + def path_dependency_details_from_npm_lockfile(parsed_lockfile) + path_starts = NPM_PATH_DEPENDENCY_STARTS + parsed_lockfile.fetch("dependencies", []).to_a + .select { |_, v| v.is_a?(Hash) } + .select { |_, v| v.fetch("version", "").start_with?(*path_starts) } + .map { |k, v| [k, v.fetch("version")] } + end + + # Re-write the glob name to the targeted dependency name (which is used + # in the lockfile), for example "parent-package/**/sub-dep/target-dep" > + # "target-dep" + sig { params(path: String, value: String).returns([String, String]) } + def convert_dependency_path_to_name(path, value) + # Picking the last two parts that might include a scope + parts = path.split("/").last(2) + parts.shift if parts.count == 2 && !T.must(parts.first).start_with?("@") + [parts.join("/"), value] + end + + sig { returns(T::Array[DependencyFile]) } + def fetch_workspace_package_jsons + return [] unless parsed_package_json["workspaces"] + + workspace_paths(parsed_package_json["workspaces"]).filter_map do |workspace| + # Skip excluded workspace directories + next if Dependabot::FileFiltering.should_exclude_path?(workspace, "workspace directory", @exclude_paths) + + fetch_package_json_if_present(workspace) + end + end + + sig { params(workspace_object: T.untyped).returns(T::Array[String]) } + def workspace_paths(workspace_object) + paths_array = + if workspace_object.is_a?(Hash) + workspace_object.values_at("packages", "nohoist").flatten.compact + elsif workspace_object.is_a?(Array) then workspace_object + else + [] # Invalid lerna.json, which must not be in use + end + + paths_array.flat_map { |path| recursive_find_directories(path) } + end + + sig { params(glob: String).returns(T::Array[String]) } + def find_directories(glob) + return [glob] unless glob.include?("*") + + unglobbed_path = + glob.gsub(%r{^\./}, "").gsub(/!\([^)]*\)/, "*") + .split("*") + .first&.gsub(%r{(?<=/)[^/]*$}, "") || "." + + dir = directory.gsub(%r{(^/|/$)}, "") + + paths = + repo_contents(dir: unglobbed_path, raise_errors: false) + .select { |file| file.type == "dir" } + .map { |f| f.path.gsub(%r{^/?#{Regexp.escape(dir)}/?}, "") } + + matching_paths(glob, paths) + end + + sig { params(glob: String, paths: T::Array[String]).returns(T::Array[String]) } + def matching_paths(glob, paths) + glob = glob.gsub(%r{^\./}, "").gsub(/!\([^)]*\)/, "*") + glob = "#{glob}/*" if glob.end_with?("**") + + paths.select { |filename| File.fnmatch?(glob, filename, File::FNM_PATHNAME) } + end + + sig { params(glob: String, prefix: String).returns(T::Array[String]) } + def recursive_find_directories(glob, prefix = "") + return [prefix + glob] unless glob.include?("*") + + glob = glob.gsub(%r{^\./}, "") + glob_parts = glob.split("/") + + current_glob = glob_parts.first + paths = find_directories(prefix + T.must(current_glob)) + next_parts = current_glob == "**" ? glob_parts : glob_parts.drop(1) + return paths if next_parts.empty? + + paths += paths.flat_map do |expanded_path| + recursive_find_directories(next_parts.join("/"), "#{expanded_path}/") + end + + matching_paths(prefix + glob, paths) + end + + sig { params(workspace: String).returns(T.nilable(DependencyFile)) } + def fetch_package_json_if_present(workspace) + file = File.join(workspace, MANIFEST_FILENAME) + + begin + fetch_file_from_host(file) + rescue Dependabot::DependencyFileNotFound + # Not all paths matched by a workspace glob may contain a package.json + # file. Ignore if that's the case + nil + end + end + + sig { returns(T.untyped) } + def parsed_package_json + parsed = JSON.parse(T.must(package_json.content)) + raise Dependabot::DependencyFileNotParseable, package_json.path unless parsed.is_a?(Hash) + + parsed + rescue JSON::ParserError + raise Dependabot::DependencyFileNotParseable, package_json.path + end + + sig { params(filename: String).returns(T.nilable(DependencyFile)) } + def fetch_file_with_support(filename) + fetch_file_from_host(filename).tap { |f| f.support_file = true } + rescue Dependabot::DependencyFileNotFound + nil + end + + sig { params(filename: String).returns(T.nilable(DependencyFile)) } + def fetch_file_from_parent_directories(filename) + (1..directory.split("/").count).each do |i| + file = fetch_file_with_support(("../" * i) + filename) + return file if file + end + nil + end + end + end +end + +Dependabot::FileFetchers + .register(Dependabot::Nub::ECOSYSTEM, Dependabot::Nub::FileFetcher) diff --git a/nub/lib/dependabot/nub/file_parser.rb b/nub/lib/dependabot/nub/file_parser.rb new file mode 100644 index 00000000000..98c2cbeafb6 --- /dev/null +++ b/nub/lib/dependabot/nub/file_parser.rb @@ -0,0 +1,495 @@ +# typed: strict +# frozen_string_literal: true + +# See https://docs.npmjs.com/files/package.json for package.json format docs. + +require "cgi/escape" +require "dependabot/dependency" +require "dependabot/file_parsers" +require "dependabot/file_parsers/base" +require "dependabot/shared_helpers" +require "dependabot/nub/helpers" +require "dependabot/nub/native_helpers" +require "dependabot/nub/version" +require "dependabot/nub/requirement" +require "dependabot/nub/package_manager" +require "dependabot/nub/registry_parser" +require "dependabot/git_metadata_fetcher" +require "dependabot/git_commit_checker" +require "dependabot/errors" +require "sorbet-runtime" + +module Dependabot + module Nub + class FileParser < Dependabot::FileParsers::Base # rubocop:disable Metrics/ClassLength + extend T::Sig + + require "dependabot/file_parsers/base/dependency_set" + require_relative "file_parser/lockfile_parser" + + DEPENDENCY_TYPES = %w(dependencies devDependencies optionalDependencies).freeze + GIT_URL_REGEX = %r{ + (?^|^git.*?|^github:|^bitbucket:|^gitlab:|github\.com/) + (?[a-z0-9-]+)/ + (?[a-z0-9_.-]+) + ( + (?:\#semver:(?.+))| + (?:\#(?=[\^~=<>*])(?.+))| + (?:\#(?.+)) + )?$ + }ix + + sig do + params( + json: T::Hash[String, T.untyped], + _block: T.proc.params(arg0: String, arg1: String, arg2: String).void + ) + .void + end + def self.each_dependency(json, &_block) + DEPENDENCY_TYPES.each do |type| + deps = json[type] || {} + deps.each do |name, requirement| + yield(name, requirement, type) + end + end + end + + sig { override.returns(T::Array[Dependency]) } + def parse + dependency_set = DependencySet.new + dependency_set += manifest_dependencies + dependency_set += lockfile_dependencies + + dependencies = Helpers.dependencies_with_all_versions_metadata(dependency_set) + + dependencies.reject do |dep| + reqs = dep.requirements + + # Ignore dependencies defined in support files, since we don't want PRs for those + support_reqs = reqs.select { |r| support_package_files.any? { |f| f.name == r.file } } + next true if support_reqs.any? + + # TODO: Currently, Dependabot can't handle dependencies that have both + # a git source *and* a non-git source. Fix that! + git_reqs = reqs.select { |r| r.source_string("type") == "git" } + next false if git_reqs.none? + next true if git_reqs.map(&:source).uniq.count > 1 + + dep.requirements.any? { |r| r.source_string("type") != "git" } + end + end + + sig { returns(Ecosystem) } + def ecosystem + @ecosystem ||= T.let( + Ecosystem.new( + name: ECOSYSTEM, + package_manager: package_manager_helper.package_manager, + language: package_manager_helper.language + ), + T.nilable(Ecosystem) + ) + end + + private + + sig { returns(PackageManagerHelper) } + def package_manager_helper + @package_manager_helper ||= T.let( + PackageManagerHelper.new( + parsed_package_json, + lockfiles, + registry_config_files, + credentials + ), + T.nilable(PackageManagerHelper) + ) + end + + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def lockfiles + { + nub: nub_lock + } + end + + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def registry_config_files + { + npmrc: npmrc + } + end + + sig { returns(T.untyped) } + def parsed_package_json + JSON.parse(T.must(package_json.content)) + rescue JSON::ParserError + raise Dependabot::DependencyFileNotParseable, package_json.path + end + + sig { returns(Dependabot::DependencyFile) } + def package_json + # Declare the instance variable with T.let and the correct type + @package_json ||= T.let( + T.must(dependency_files.find { |f| f.name == MANIFEST_FILENAME }), + T.nilable(Dependabot::DependencyFile) + ) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def nub_lock + @nub_lock ||= T.let( + dependency_files.find do |f| + f.name.end_with?(NubPackageManager::LOCKFILE_NAME) + end, + T.nilable(Dependabot::DependencyFile) + ) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def npmrc + @npmrc ||= T.let( + dependency_files.find do |f| + f.name.end_with?(NubPackageManager::RC_FILENAME) + end, + T.nilable(Dependabot::DependencyFile) + ) + end + + sig { returns(Dependabot::FileParsers::Base::DependencySet) } + def manifest_dependencies + dependency_set = DependencySet.new + + package_files.each do |file| + json = JSON.parse(T.must(file.content)) + + # TODO: Currently, Dependabot can't handle flat dependency files + # (and will error at the FileUpdater stage, because the + # UpdateChecker doesn't take account of flat resolution). + next if json["flat"] + + self.class.each_dependency(json) do |name, requirement, type| + next unless requirement.is_a?(String) + + # Skip dependencies using Yarn workspace cross-references as requirements + next if requirement.start_with?("workspace:", "catalog:") + + requirement = "*" if requirement == "" + dep = build_dependency( + file: file, type: type, name: name, requirement: requirement + ) + dependency_set << dep if dep + end + end + + dependency_set + end + + sig { returns(LockfileParser) } + def lockfile_parser + @lockfile_parser ||= T.let( + LockfileParser.new( + dependency_files: dependency_files + ), + T.nilable(Dependabot::Nub::FileParser::LockfileParser) + ) + end + + sig { returns(Dependabot::FileParsers::Base::DependencySet) } + def lockfile_dependencies + lockfile_parser.parse_set + end + + sig do + params(file: DependencyFile, type: T.untyped, name: String, requirement: String) + .returns(T.nilable(Dependency)) + end + def build_dependency(file:, type:, name:, requirement:) + lockfile_details = lockfile_parser.lockfile_details( + dependency_name: name, + requirement: requirement, + manifest_name: file.name + ) + version = version_for(requirement, lockfile_details) + converted_version = T.let( + if version.nil? + nil + elsif version.is_a?(String) + version + else + Dependabot::Version.new(version) + end, + T.nilable(T.any(String, Dependabot::Version)) + ) + + return if lockfile_details && !version + return if ignore_requirement?(requirement) + return if workspace_package_names.include?(name) + + # TODO: Handle aliased packages: + # https://github.com/dependabot/dependabot-core/pull/1115 + # + # Ignore dependencies with an alias in the name + # Example: "my-fetch-factory@npm:fetch-factory" + return if aliased_package_name?(name) + + Dependency.new( + name: name, + version: converted_version, + package_manager: ECOSYSTEM, + requirements: [{ + requirement: requirement_for(requirement), + file: file.name, + groups: [type], + source: source_for(name, requirement, lockfile_details) + }] + ) + end + + sig { override.void } + def check_required_files + return if get_original_file(MANIFEST_FILENAME) + + raise DependencyFileNotFound.new( + nil, + "#{MANIFEST_FILENAME} not found." + ) + end + + sig { params(requirement: String).returns(T::Boolean) } + def ignore_requirement?(requirement) + return true if local_path?(requirement) + return true if non_git_url?(requirement) + + # TODO: Handle aliased packages: + # https://github.com/dependabot/dependabot-core/pull/1115 + alias_package?(requirement) + end + + sig { params(requirement: String).returns(T::Boolean) } + def local_path?(requirement) + requirement.start_with?("link:", "file:", "/", "./", "../", "~/") + end + + sig { params(requirement: String).returns(T::Boolean) } + def alias_package?(requirement) + requirement.start_with?("#{NubPackageManager::NAME}:") + end + + sig { params(requirement: String).returns(T::Boolean) } + def non_git_url?(requirement) + requirement.include?("://") && !git_url?(requirement) + end + + sig { params(requirement: String).returns(T::Boolean) } + def git_url?(requirement) + requirement.match?(GIT_URL_REGEX) + end + + sig { params(requirement: String).returns(T::Boolean) } + def git_url_with_semver?(requirement) + return false unless git_url?(requirement) + + !T.must(requirement.match(GIT_URL_REGEX)).named_captures.fetch("semver").nil? + end + + sig { params(name: String).returns(T::Boolean) } + def aliased_package_name?(name) + name.include?("@#{NubPackageManager::NAME}:") + end + + sig { returns(T::Array[String]) } + def workspace_package_names + @workspace_package_names ||= T.let( + package_files.filter_map do |f| + JSON.parse(T.must(f.content))["name"] + end, + T.nilable(T::Array[String]) + ) + end + + sig do + params(requirement: String, lockfile_details: T.nilable(T::Hash[String, T.untyped])) + .returns(T.nilable(T.any(String, Integer, Gem::Version))) + end + def version_for(requirement, lockfile_details) + if git_url_with_semver?(requirement) + semver_version = lockfile_version_for(lockfile_details) + return semver_version if semver_version + + git_revision = git_revision_for(lockfile_details) + version_from_git_revision(requirement, git_revision) || git_revision + elsif git_url?(requirement) + git_revision_for(lockfile_details) + elsif lockfile_details + lockfile_version_for(lockfile_details) + else + exact_version = exact_version_for(requirement) + return unless exact_version + + semver_version_for(exact_version) + end + end + + sig { params(lockfile_details: T.nilable(T::Hash[String, T.untyped])).returns(T.nilable(String)) } + def git_revision_for(lockfile_details) + version = T.cast(lockfile_details&.fetch("version", nil), T.nilable(String)) + resolved = T.cast(lockfile_details&.fetch("resolved", nil), T.nilable(String)) + [ + version&.split("#")&.last, + resolved&.split("#")&.last, + resolved&.split("/")&.last + ].find { |str| commit_sha?(str) } + end + + sig { params(string: T.nilable(String)).returns(T::Boolean) } + def commit_sha?(string) + return false unless string.is_a?(String) + + string.match?(/^[0-9a-f]{40}$/) + end + + sig { params(requirement: String, git_revision: T.nilable(String)).returns(T.nilable(String)) } + def version_from_git_revision(requirement, git_revision) + tags = + Dependabot::GitMetadataFetcher.new( + url: git_source_for(requirement).fetch(:url), + credentials: credentials + ).tags + .select { |t| [t.commit_sha, t.tag_sha].include?(git_revision) } + + tags.each do |t| + next unless t.name.match?(Dependabot::GitCommitChecker::VERSION_REGEX) + + version = T.must(t.name.match(Dependabot::GitCommitChecker::VERSION_REGEX)) + .named_captures.fetch("version") + next unless version_class.correct?(version) + + return version + end + + nil + rescue Dependabot::GitDependenciesNotReachable + nil + end + + sig do + params(lockfile_details: T.nilable(T::Hash[String, T.untyped])) + .returns(T.nilable(T.any(String, Integer, Gem::Version))) + end + def lockfile_version_for(lockfile_details) + semver_version_for(lockfile_details&.fetch("version", "")) + end + + sig { params(version: T.nilable(String)).returns(T.nilable(T.any(String, Integer, Gem::Version))) } + def semver_version_for(version) + version_class.semver_for(version) + end + + sig { params(requirement: String).returns(T.nilable(String)) } + def exact_version_for(requirement) + req = requirement_class.new(requirement) + return unless req.exact? + + req.requirements.first.last.to_s + rescue Gem::Requirement::BadRequirementError + # If it doesn't parse, it's definitely not exact + end + + sig do + params(name: String, requirement: String, lockfile_details: T.nilable(T::Hash[String, T.untyped])) + .returns(T.nilable(T::Hash[Symbol, T.untyped])) + end + def source_for(name, requirement, lockfile_details) + return git_source_for(requirement) if git_url?(requirement) + + resolved_url = lockfile_details&.fetch("resolved", nil) + + resolution = lockfile_details&.fetch("resolution", nil) + package_match = resolution&.match(/__archiveUrl=(?.+)/) + resolved_url = CGI.unescape(package_match.named_captures.fetch("package_url", "")) if package_match + + return unless resolved_url + return unless resolved_url.start_with?("http") + return if resolved_url.match?(/(?\S+):registry\s*=\s*(?\S+)/ + + sig do + params( + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential], + dependencies: T::Array[Dependabot::Dependency] + ).void + end + def initialize(dependency_files:, credentials:, dependencies: []) + @dependency_files = dependency_files + @credentials = credentials + @dependencies = dependencies + end + + # PROXY WORK + sig { returns(String) } + def npmrc_content + initial_content = + if npmrc_file then complete_npmrc_from_credentials + else + build_npmrc_content_from_lockfile + end + + final_content = initial_content || "" + + return final_content unless registry_credentials.any? + + credential_lines_for_npmrc.each do |credential_line| + next if final_content.include?(credential_line) + + final_content = [final_content, credential_line].reject(&:empty?).join("\n") + end + + final_content + end + + private + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T::Array[Dependabot::Dependency]) } + attr_reader :dependencies + + sig { returns(T.nilable(String)) } + def build_npmrc_content_from_lockfile + return unless global_registry + + registry = T.must(global_registry)["registry"] + registry = "https://#{registry}" unless registry&.start_with?("http") + "registry = #{registry}\n" \ + "#{npmrc_global_registry_auth_line}" \ + "always-auth = true" + end + + # rubocop:disable Metrics/PerceivedComplexity + # rubocop:disable Metrics/CyclomaticComplexity + sig { returns(T.nilable(Dependabot::Credential)) } + def global_registry + return @global_registry if defined?(@global_registry) + + @global_registry = T.let( + registry_credentials.find do |cred| + next false if CENTRAL_REGISTRIES.include?(cred["registry"]) + + # If all the URLs include this registry, it's global + next true if dependency_urls&.size&.positive? && dependency_urls&.all? do |url| + url.include?(T.must(cred["registry"])) + end + + # Check if this registry has already been defined in .npmrc as a scoped registry + next false if npmrc_scoped_registries&.any? { |sr| sr.include?(T.must(cred["registry"])) } + + # If any unscoped URLs include this registry, assume it's global + dependency_urls + &.reject { |u| u.include?("@") || u.include?("%40") } + &.any? { |url| url.include?(T.must(cred["registry"])) } + end, + T.nilable(Dependabot::Credential) + ) + end + # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Metrics/CyclomaticComplexity + sig { returns(String) } + def npmrc_global_registry_auth_line + # This token is passed in from the Dependabot Config + # We write it to the .npmrc file so that it can be used by the VulnerabilityAuditor + token = global_registry&.fetch("token", nil) + return "" unless token + + auth_line(token, global_registry&.fetch("registry")) + "\n" + end + + sig { returns(T.nilable(T::Array[String])) } + def dependency_urls + return @dependency_urls if defined?(@dependency_urls) + + @dependency_urls = [] + + if dependencies.any? + @dependency_urls = dependencies.map do |dependency| + Package::RegistryFinder.new( + dependency: dependency, + credentials: credentials, + npmrc_file: npmrc_file + ).dependency_url + end + return @dependency_urls + end + + # The registry URL for Bintray goes into the lockfile in a + # modified format, so we modify it back before checking against + # our credentials + @dependency_urls = T.let( + @dependency_urls.map do |url| + url.gsub("dl.bintray.com//", "api.bintray.com/npm/") + end, + T.nilable(T::Array[String]) + ) + end + sig { returns(String) } + def complete_npmrc_from_credentials + # removes attribute timeout to allow for job update, + # having a timeout=xxxxx value is causing some jobs to fail + initial_content = T.must(T.must(npmrc_file).content) + .gsub(/^.*\$\{.*\}.*/, "").strip.gsub(/^timeout.*/, "").strip + "\n" + + return initial_content unless global_registry + + registry = T.must(global_registry)["registry"] + registry = "https://#{registry}" unless registry&.start_with?("http") + initial_content + + "registry = #{registry}\n" \ + "#{npmrc_global_registry_auth_line}" \ + "always-auth = true\n" + end + + sig { returns(T::Array[String]) } + def credential_lines_for_npmrc + lines = T.let([], T::Array[String]) + registry_credentials.each do |cred| + registry = cred.fetch("registry") + + lines += T.must(registry_scopes(registry)) if registry_scopes(registry) + + token = cred.fetch("token", nil) + next unless token + + lines << auth_line(token, registry) + end + + return lines unless lines.any? { |str| str.include?("auth=") } + + # Work around a suspected yarn bug + ["always-auth = true"] + lines + end + + sig { params(token: String, registry: T.nilable(String)).returns(String) } + def auth_line(token, registry = nil) + auth = if token.include?(":") + encoded_token = Base64.encode64(token).delete("\n") + "_auth=#{encoded_token}" + elsif Base64.decode64(token).ascii_only? && + Base64.decode64(token).include?(":") + "_auth=#{token.delete("\n")}" + else + "_authToken=#{token}" + end + + return auth unless registry + + # We need to ensure the registry uri ends with a trailing slash in the npmrc file + # but we do not want to add one if it already exists + registry_with_trailing_slash = registry.sub(%r{\/?$}, "/") + + "//#{registry_with_trailing_slash}:#{auth}" + end + + sig { returns(T.nilable(T::Array[String])) } + def npmrc_scoped_registries + return [] unless npmrc_file + + @npmrc_scoped_registries ||= T.let( + T.must(T.must(npmrc_file).content).lines.select { |line| line.match?(SCOPED_REGISTRY) } + .filter_map { |line| line.match(SCOPED_REGISTRY)&.named_captures&.fetch("registry") }, + T.nilable(T::Array[String]) + ) + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { params(registry: String).returns(T.nilable(T::Array[String])) } + def registry_scopes(registry) + # Central registries don't just apply to scopes + return if CENTRAL_REGISTRIES.include?(registry) + return unless dependency_urls + + other_regs = + registry_credentials.map { |c| c.fetch("registry") } - + [registry] + affected_urls = + dependency_urls + &.select do |url| + next false unless url.include?(registry) + + other_regs.none? { |r| r.include?(registry) && url.include?(r) } + end + + scopes = T.must(affected_urls).map do |url| + url.split(/\%40|@/)[1]&.split(%r{\%2[fF]|/})&.first + end.uniq + + # Registry used for unscoped packages + return if scopes.include?(nil) + + scopes.map { |scope| "@#{scope}:registry=https://#{registry}" } + end + # rubocop:enable Metrics/PerceivedComplexity + + sig { returns(T::Array[Dependabot::Credential]) } + def registry_credentials + credentials.select { |cred| cred.fetch("type") == "npm_registry" } + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def npmrc_file + @npmrc_file ||= T.let( + dependency_files.find { |f| f.name.end_with?(".npmrc") }, + T.nilable(Dependabot::DependencyFile) + ) + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/file_updater/nub_lockfile_updater.rb b/nub/lib/dependabot/nub/file_updater/nub_lockfile_updater.rb new file mode 100644 index 00000000000..1c775d9d559 --- /dev/null +++ b/nub/lib/dependabot/nub/file_updater/nub_lockfile_updater.rb @@ -0,0 +1,208 @@ +# typed: strong +# frozen_string_literal: true + +require "json" +require "sorbet-runtime" + +require "dependabot/nub/helpers" +require "dependabot/nub/package/registry_finder" +require "dependabot/nub/registry_parser" +require "dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater" +require "dependabot/shared_helpers" + +module Dependabot + module Nub + class FileUpdater < Dependabot::FileUpdaters::Base + class NubLockfileUpdater + extend T::Sig + + require_relative "npmrc_builder" + require_relative "package_json_updater" + + sig do + params( + dependencies: T::Array[Dependabot::Dependency], + dependency_files: T::Array[Dependabot::DependencyFile], + repo_contents_path: String, + credentials: T::Array[Dependabot::Credential] + ) + .void + end + def initialize(dependencies:, dependency_files:, repo_contents_path:, credentials:) + @dependencies = dependencies + @dependency_files = dependency_files + @repo_contents_path = repo_contents_path + @credentials = credentials + end + + sig { params(nub_lock: Dependabot::DependencyFile).returns(String) } + def updated_nub_lock_content(nub_lock) + @updated_nub_lock_content ||= T.let({}, T.nilable(T::Hash[String, String])) + return T.must(@updated_nub_lock_content[nub_lock.name]) if @updated_nub_lock_content[nub_lock.name] + + new_content = run_nub_update(nub_lock: nub_lock) + @updated_nub_lock_content[nub_lock.name] = new_content + rescue SharedHelpers::HelperSubprocessFailed => e + handle_nub_lock_updater_error(e, nub_lock) + end + + private + + sig { returns(T::Array[Dependabot::Dependency]) } + attr_reader :dependencies + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(String) } + attr_reader :repo_contents_path + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + ERR_PATTERNS = T.let( + { + /get .* 404/i => Dependabot::DependencyNotFound, + /installfailed cloning repository/i => Dependabot::DependencyNotFound, + /file:.* failed to resolve/i => Dependabot::DependencyNotFound, + /no version matching/i => Dependabot::DependencyFileNotResolvable, + /failed to resolve/i => Dependabot::DependencyFileNotResolvable + }.freeze, + T::Hash[Regexp, Dependabot::DependabotError] + ) + + sig { params(nub_lock: Dependabot::DependencyFile).returns(String) } + def run_nub_update(nub_lock:) + SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do + File.write(".npmrc", npmrc_content(nub_lock)) + + SharedHelpers.with_git_configured(credentials: credentials) do + # Write the final manifests (PackageJsonUpdater already applied the new requirements / + # git refs), then update the lockfile in one shot. `nub update @` (nub >= 0.4.1) + # pins registry deps — INCLUDING transitive/sub-dependencies not present in any manifest — + # to the exact version Dependabot chose; `--no-save` leaves the manifests untouched. A + # final lockfile-only install settles git deps and anything the update didn't cover. + # Mirrors npm_and_yarn's pnpm updater. + write_final_package_json_files + run_nub_update_packages + run_nub_install + + File.read(nub_lock.name) + end + end + end + + sig { void } + def run_nub_update_packages + updates = dependencies + .reject { |dep| git_dependency?(dep) } + .filter_map { |dep| "#{dep.name}@#{dep.version}" if dep.version } + return if updates.empty? + + Helpers.run_nub_command( + "update #{updates.join(' ')} --lockfile-only --no-save --ignore-scripts", + fingerprint: "update --lockfile-only --no-save --ignore-scripts" + ) + end + + sig { void } + def run_nub_install + Helpers.run_nub_command( + "install --lockfile-only --ignore-scripts", + fingerprint: "install --lockfile-only --ignore-scripts" + ) + end + + sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) } + def git_dependency?(dependency) + dependency.requirements.any? { |req| req.source_string("type") == "git" } + end + + sig { params(lockfile: Dependabot::DependencyFile).returns(T::Array[Dependabot::Dependency]) } + def lockfile_dependencies(lockfile) + @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependabot::Dependency]])) + @lockfile_dependencies[lockfile.name] ||= + Nub::FileParser.new( + dependency_files: [lockfile, *package_files], + source: nil, + credentials: credentials + ).parse + end + + sig do + params(error: SharedHelpers::HelperSubprocessFailed, _nub_lock: Dependabot::DependencyFile) + .returns(T.noreturn) + end + def handle_nub_lock_updater_error(error, _nub_lock) + # nub.lock is pnpm-lock v9 and nub surfaces pnpm-format engine errors, so map them + # through npm_and_yarn's pnpm handler (duplicates, no-versions, ECONNRESET, ...) before + # falling back to nub's own registry/network patterns below. + Dependabot::NpmAndYarn::PnpmErrorHandler.new( + dependencies: dependencies, + dependency_files: dependency_files + ).handle_pnpm_error(error) + + error_message = error.message + ERR_PATTERNS.each do |pattern, error_class| + raise error_class, error_message if error_message.match?(pattern) + end + + raise error + end + + sig { void } + def write_final_package_json_files + package_files.each do |file| + path = file.name + FileUtils.mkdir_p(Pathname.new(path).dirname) + File.write(path, updated_package_json_content(file)) + end + end + + sig { params(nub_lock: Dependabot::DependencyFile).returns(String) } + def npmrc_content(nub_lock) + NpmrcBuilder.new( + credentials: credentials, + dependency_files: dependency_files, + dependencies: lockfile_dependencies(nub_lock) + ).npmrc_content + end + + sig { params(file: Dependabot::DependencyFile).returns(String) } + def updated_package_json_content(file) + @updated_package_json_content ||= T.let({}, T.nilable(T::Hash[String, String])) + @updated_package_json_content[file.name] ||= + T.must( + PackageJsonUpdater.new( + package_json: file, + dependencies: dependencies + ).updated_package_json.content + ) + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def package_files + @package_files ||= T.let( + dependency_files.select { |f| f.name.end_with?("package.json") }, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) + end + + sig { returns(String) } + def base_dir + T.must(dependency_files.first).directory + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def npmrc_file + dependency_files.find { |f| f.name == ".npmrc" } + end + + sig { params(message: String).returns(String) } + def sanitize_message(message) + message.gsub(/"|\[|\]|\}|\{/, "") + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/file_updater/package_json_preparer.rb b/nub/lib/dependabot/nub/file_updater/package_json_preparer.rb new file mode 100644 index 00000000000..a7ee25c648d --- /dev/null +++ b/nub/lib/dependabot/nub/file_updater/package_json_preparer.rb @@ -0,0 +1,15 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/file_updater/package_json_preparer" +require "dependabot/nub/file_updater" + +# Manifest preparation (ssh-source swap, workspace-prefix cleanup) is identical +# across pnpm-format tools; delegate to npm_and_yarn's PackageJsonPreparer. +module Dependabot + module Nub + class FileUpdater < Dependabot::FileUpdaters::Base + PackageJsonPreparer = Dependabot::NpmAndYarn::FileUpdater::PackageJsonPreparer + end + end +end diff --git a/nub/lib/dependabot/nub/file_updater/package_json_updater.rb b/nub/lib/dependabot/nub/file_updater/package_json_updater.rb new file mode 100644 index 00000000000..0c526e73ed1 --- /dev/null +++ b/nub/lib/dependabot/nub/file_updater/package_json_updater.rb @@ -0,0 +1,371 @@ +# typed: strict +# frozen_string_literal: true + +require "sorbet-runtime" + +require "dependabot/nub/file_updater" + +module Dependabot + module Nub + class FileUpdater < Dependabot::FileUpdaters::Base + class PackageJsonUpdater + extend T::Sig + + LOCAL_PACKAGE = T.let([/portal:/, /file:/].freeze, T::Array[Regexp]) + + PATCH_PACKAGE = T.let([/patch:/].freeze, T::Array[Regexp]) + + sig do + params( + package_json: Dependabot::DependencyFile, + dependencies: T::Array[Dependabot::Dependency] + ).void + end + def initialize(package_json:, dependencies:) + @package_json = package_json + @dependencies = dependencies + end + + sig { returns(Dependabot::DependencyFile) } + def updated_package_json + updated_file = package_json.dup + updated_file.content = updated_package_json_content + updated_file + end + + private + + sig { returns(Dependabot::DependencyFile) } + attr_reader :package_json + + sig { returns(T::Array[Dependabot::Dependency]) } + attr_reader :dependencies + + sig { returns(T.nilable(String)) } + def updated_package_json_content + # checks if we are updating single dependency in package.json + unique_deps_count = dependencies.map(&:name).to_a.uniq.compact.length + + dependencies.reduce(package_json.content.dup) do |content, dep| + updated_requirements(dep)&.each do |new_req| + old_req = old_requirement(dep, new_req) + + new_content = update_package_json_declaration( + package_json_content: T.must(content), + dependency_name: dep.name, + old_req: old_req, + new_req: new_req + ) + + # package.json does not always contain the same dependencies compared to the + # "dependencies" list. For example, the dependencies object can contain same name dependency + # "dep" => "1.0.0" and "dev" => "1.0.1" while package.json can only contain "dep" => "1.0.0". + # The other dependency is not present in package.json so we don't have to update it — this is + # most likely a transitive dependency which only needs an update in the lockfile. For a batch + # with a single unique dependency name we tolerate this no-op update, but when multiple unique + # dependencies are being updated and none change the content we treat that as unexpected and raise. + raise "Expected content to change!" if content == new_content && unique_deps_count > 1 + + content = new_content + end + + new_requirements(dep).each do |new_req| + old_req = old_requirement(dep, new_req) + + content = update_package_json_resolutions( + package_json_content: T.must(content), + new_req: new_req, + dependency: dep, + old_req: old_req + ) + end + + content + end + end + sig do + params( + dependency: Dependabot::Dependency, + new_requirement: T::Hash[Symbol, T.untyped] + ) + .returns(T.nilable(T::Hash[Symbol, T.untyped])) + end + def old_requirement(dependency, new_requirement) + T.must(dependency.previous_requirements) + .select { |r| r[:file] == package_json.name } + .find { |r| r[:groups] == new_requirement[:groups] } + end + + sig { params(dependency: Dependabot::Dependency).returns(T::Array[T::Hash[Symbol, T.untyped]]) } + def new_requirements(dependency) + dependency.requirements.select { |r| r[:file] == package_json.name } + end + + sig { params(dependency: Dependabot::Dependency).returns(T.nilable(T::Array[T::Hash[Symbol, T.untyped]])) } + def updated_requirements(dependency) + return unless dependency.previous_requirements + + preliminary_check_for_update(dependency) + + updated_requirement_pairs = + dependency.requirements.zip(T.must(dependency.previous_requirements)) + .reject do |new_req, old_req| + next true if new_req == old_req + next false unless old_req&.fetch(:source).nil? + + new_req[:requirement] == old_req&.fetch(:requirement) + end + + updated_requirement_pairs + .map(&:first) + .select { |r| r[:file] == package_json.name } + end + + sig do + params( + package_json_content: String, + new_req: T::Hash[Symbol, T.untyped], + dependency_name: String, + old_req: T.nilable(T::Hash[Symbol, T.untyped]) + ) + .returns(String) + end + def update_package_json_declaration(package_json_content:, new_req:, dependency_name:, old_req:) + original_line = declaration_line( + dependency_name: dependency_name, + dependency_req: old_req, + content: package_json_content + ) + + replacement_line = replacement_declaration_line( + original_line: original_line, + old_req: old_req, + new_req: new_req + ) + + groups = new_req.fetch(:groups) + + update_package_json_sections( + groups, + package_json_content, + original_line, + replacement_line + ) + end + + # For full details on how Yarn resolutions work, see + # https://github.com/yarnpkg/rfcs/blob/master/implemented/ + # 0000-selective-versions-resolutions.md + sig do + params( + package_json_content: String, + new_req: T::Hash[Symbol, T.untyped], + dependency: Dependabot::Dependency, + old_req: T.nilable(T::Hash[Symbol, T.untyped]) + ) + .returns(String) + end + def update_package_json_resolutions(package_json_content:, new_req:, dependency:, old_req:) + dep = dependency + parsed_json_content = JSON.parse(package_json_content) + resolutions = + parsed_json_content.fetch("resolutions", parsed_json_content.dig("pnpm", "overrides") || {}) + .reject { |_, v| v != old_req && v != dep.previous_version } + .select { |k, _| k == dep.name || k.end_with?("/#{dep.name}") } + + return package_json_content unless resolutions.any? + + content = package_json_content + resolutions.each do |_, resolution| + original_line = declaration_line( + dependency_name: dep.name, + dependency_req: { requirement: resolution }, + content: content + ) + + new_resolution = resolution == old_req ? new_req : dep.version + + replacement_line = replacement_declaration_line( + original_line: original_line, + old_req: { requirement: resolution }, + new_req: { requirement: new_resolution } + ) + + content = update_package_json_sections( + %w(resolutions overrides), content, original_line, replacement_line + ) + end + content + end + + sig do + params( + dependency_name: String, + dependency_req: T.nilable(T::Hash[Symbol, T.untyped]), + content: String + ) + .returns(String) + end + def declaration_line(dependency_name:, dependency_req:, content:) + git_dependency = dependency_req&.dig(:source, :type) == "git" + + unless git_dependency + requirement = dependency_req&.fetch(:requirement) + return content.match( + /"#{Regexp.escape(dependency_name)}"\s*:\s* + "#{Regexp.escape(requirement)}"/x + ).to_s + end + + username, repo = + dependency_req&.dig(:source, :url)&.split("/")&.last(2) + + content.match( + %r{"#{Regexp.escape(dependency_name)}"\s*:\s* + ".*?#{Regexp.escape(username)}/#{Regexp.escape(repo)}.*"}x + ).to_s + end + + sig do + params( + original_line: String, + old_req: T.nilable(T::Hash[Symbol, T.untyped]), + new_req: T::Hash[Symbol, T.untyped] + ) + .returns(String) + end + def replacement_declaration_line(original_line:, old_req:, new_req:) + was_git_dependency = old_req&.dig(:source, :type) == "git" + now_git_dependency = new_req.dig(:source, :type) == "git" + + unless was_git_dependency + return original_line.gsub( + %("#{old_req&.fetch(:requirement)}"), + %("#{new_req.fetch(:requirement)}") + ) + end + + unless now_git_dependency + return original_line.gsub( + /(?<=\s").*[^\\](?=")/, + new_req.fetch(:requirement) + ) + end + + if original_line.match?(/#[\^~=<>]|semver:/) + return update_git_semver_requirement( + original_line: original_line, + old_req: old_req, + new_req: new_req + ) + end + + original_line.gsub( + %(##{old_req&.dig(:source, :ref)}"), + %(##{new_req.dig(:source, :ref)}") + ) + end + + sig do + params( + original_line: String, + old_req: T.nilable(T::Hash[Symbol, String]), + new_req: T::Hash[Symbol, String] + ) + .returns(String) + end + def update_git_semver_requirement(original_line:, old_req:, new_req:) + if original_line.include?("semver:") + return original_line.gsub( + %(semver:#{old_req&.fetch(:requirement)}"), + %(semver:#{new_req.fetch(:requirement)}") + ) + end + + raise "Not a semver req!" unless original_line.match?(/#[\^~=<>]/) + + original_line.gsub( + %(##{old_req&.fetch(:requirement)}"), + %(##{new_req.fetch(:requirement)}") + ) + end + + sig do + params( + sections: T::Array[String], + content: String, + old_line: String, + new_line: String + ) + .returns(String) + end + def update_package_json_sections(sections, content, old_line, new_line) + # Currently, Dependabot doesn't update peerDependencies. However, + # if a development dependency is being updated and its requirement + # matches the requirement on a peer dependency we probably want to + # update the peer too. + # + # TODO: Move this logic to the UpdateChecker (and parse peer deps) + sections += ["peerDependencies"] + sections_regex = /#{sections.join('|')}/ + + declaration_blocks = T.let([], T::Array[String]) + + content.scan(/['"]#{sections_regex}['"]\s*:\s*\{/m) do + mtch = T.must(Regexp.last_match) + declaration_blocks << + (mtch.to_s + T.must(mtch.post_match[0..closing_bracket_index(mtch.post_match)])) + end + + declaration_blocks.reduce(content.dup) do |new_content, block| + updated_block = block.sub(old_line, new_line) + new_content.sub(block, updated_block) + end + end + + sig { params(string: String).returns(Integer) } + def closing_bracket_index(string) + closes_required = 1 + + string.chars.each_with_index do |char, index| + closes_required += 1 if char == "{" + closes_required -= 1 if char == "}" + return index if closes_required.zero? + end + + 0 + end + + sig { params(dependency: Dependabot::Dependency).void } + def preliminary_check_for_update(dependency) + T.must(dependency.previous_requirements).each do |req, _dep| + requirement = req.requirement + next if requirement.nil? + + # some deps are patched with local patches, we don't need to update them + if requirement.match?(Regexp.union(PATCH_PACKAGE)) + Dependabot.logger.info( + "Func: updated_requirements. dependency patched #{dependency.name}," \ + " Requirement: '#{requirement}'" + ) + + raise DependencyFileNotResolvable, + "Dependency is patched locally, Update not required." + end + + # some deps are added as local packages, we don't need to update them as they are referred to a local path + next unless requirement.match?(Regexp.union(LOCAL_PACKAGE)) + + Dependabot.logger.info( + "Func: updated_requirements. local package #{dependency.name}," \ + " Requirement: '#{requirement}'" + ) + + raise DependencyFileNotResolvable, + "Local package, Update not required." + end + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/helpers.rb b/nub/lib/dependabot/nub/helpers.rb new file mode 100644 index 00000000000..d25d18b3ddc --- /dev/null +++ b/nub/lib/dependabot/nub/helpers.rb @@ -0,0 +1,93 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/dependency" +require "dependabot/file_parsers" +require "dependabot/file_parsers/base" +require "dependabot/shared_helpers" +require "sorbet-runtime" + +module Dependabot + module Nub + module Helpers + extend T::Sig + + # NUB Version Constants + NUB_V1 = 1 + NUB_DEFAULT_VERSION = NUB_V1 + + sig { params(_nub_lock: T.nilable(DependencyFile)).returns(Integer) } + def self.nub_version_numeric(_nub_lock) + NUB_DEFAULT_VERSION + end + + sig { returns(T.nilable(String)) } + def self.node_version + version = run_node_command("-v", fingerprint: "-v").strip + + # Validate the output format (e.g., "v20.18.1" or "20.18.1") + if version.match?(/^v?\d+(\.\d+){2}$/) + version.strip.delete_prefix("v") # Remove the "v" prefix if present + end + rescue StandardError => e + Dependabot.logger.error("Error retrieving Node.js version: #{e.message}") + nil + end + + sig { params(command: String, fingerprint: T.nilable(String)).returns(String) } + def self.run_node_command(command, fingerprint: nil) + full_command = "node #{command}" + + Dependabot.logger.info("Running node command: #{full_command}") + + result = Dependabot::SharedHelpers.run_shell_command( + full_command, + fingerprint: "node #{fingerprint || command}" + ) + + Dependabot.logger.info("Command executed successfully: #{full_command}") + result + rescue StandardError => e + Dependabot.logger.error("Error running node command: #{full_command}, Error: #{e.message}") + raise + end + + sig { returns(T.nilable(String)) } + def self.nub_version + version = run_nub_command("--version", fingerprint: "--version").strip + if version.include?("+") + version.split("+").first # Remove build info, if present + end + rescue StandardError => e + Dependabot.logger.error("Error retrieving Nub version: #{e.message}") + nil + end + + sig { params(command: String, fingerprint: T.nilable(String)).returns(String) } + def self.run_nub_command(command, fingerprint: nil) + full_command = "nub #{command}" + + Dependabot.logger.info("Running nub command: #{full_command}") + + result = Dependabot::SharedHelpers.run_shell_command( + full_command, + fingerprint: "nub #{fingerprint || command}" + ) + + Dependabot.logger.info("Command executed successfully: #{full_command}") + result + rescue StandardError => e + Dependabot.logger.error("Error running nub command: #{full_command}, Error: #{e.message}") + raise + end + + sig { params(dependency_set: Dependabot::FileParsers::Base::DependencySet).returns(T::Array[Dependency]) } + def self.dependencies_with_all_versions_metadata(dependency_set) + dependency_set.dependencies.map do |dependency| + dependency.metadata[:all_versions] = dependency_set.all_versions_for_name(dependency.name) + dependency + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/language.rb b/nub/lib/dependabot/nub/language.rb new file mode 100644 index 00000000000..90a2239138d --- /dev/null +++ b/nub/lib/dependabot/nub/language.rb @@ -0,0 +1,46 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/nub/package_manager" + +module Dependabot + module Nub + class Language < Ecosystem::VersionManager + extend T::Sig + + NAME = "node" + + SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::Nub::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end diff --git a/nub/lib/dependabot/nub/metadata_finder.rb b/nub/lib/dependabot/nub/metadata_finder.rb new file mode 100644 index 00000000000..2093130fa42 --- /dev/null +++ b/nub/lib/dependabot/nub/metadata_finder.rb @@ -0,0 +1,292 @@ +# typed: strict +# frozen_string_literal: true + +require "excon" +require "sorbet-runtime" +require "time" + +require "dependabot/metadata_finders" +require "dependabot/metadata_finders/base" +require "dependabot/registry_client" +require "dependabot/nub/package/registry_finder" +require "dependabot/nub/version" + +module Dependabot + module Nub + class MetadataFinder < Dependabot::MetadataFinders::Base + extend T::Sig + + # RFC 3986 unreserved; others need encoding (explicit ASCII class avoids UTF-8 \w issues) + CHARS_REQUIRING_ENCODING = /[^A-Za-z0-9._~-]/ + private_constant :CHARS_REQUIRING_ENCODING + + sig { override.returns(T.nilable(String)) } + def homepage_url + # Attempt to use version_listing first, as fetching the entire listing + # array can be slow (if it's large) + return latest_version_listing["homepage"] if latest_version_listing["homepage"] + + listing = all_version_listings.find { |_, l| l["homepage"] } + listing&.last&.fetch("homepage", nil) || super + end + + sig { override.returns(T.nilable(String)) } + def maintainer_changes + releaser = npm_releaser + return unless releaser + return unless npm_listing.dig("time", dependency.version) + return if previous_releasers&.include?(releaser) + + encoded_releaser = encode_npm_releaser(releaser) + "This version was pushed to npm by " \ + "[#{releaser}](https://www.npmjs.com/~#{encoded_releaser}), a new " \ + "releaser for #{dependency.name} since your current version." + end + + private + + # Percent-encodes npm releaser names for safe inclusion in npmjs.com profile URLs. + sig { params(releaser: String).returns(String) } + def encode_npm_releaser(releaser) + return releaser unless releaser.match?(CHARS_REQUIRING_ENCODING) + + releaser.gsub(CHARS_REQUIRING_ENCODING) do |char| + char.bytes.map { |byte| "%#{format('%02X', byte)}" }.join + end + end + + sig { override.returns(T.nilable(Dependabot::Source)) } + def look_up_source + return find_source_from_registry if new_source.nil? + + source_type = new_source&.[](:type) || new_source&.fetch("type") + + case source_type + when "git" then find_source_from_git_url + when "registry" then find_source_from_registry + else raise "Unexpected source type: #{source_type}" + end + end + + sig { returns(T.nilable(String)) } + def npm_releaser + all_version_listings + .find { |v, _| v == dependency.version } + &.last&.dig("_npmUser", "name") + end + + sig { returns(T.nilable(T::Array[String])) } + def previous_releasers + times = npm_listing.fetch("time") + + cutoff = + if dependency.previous_version && times[dependency.previous_version] + Time.parse(times[dependency.previous_version]) + elsif times[dependency.version] + Time.parse(times[dependency.version]) - 1 + end + return unless cutoff + + all_version_listings + .reject { |v, _| Time.parse(times[v]) > cutoff } + .filter_map { |_, d| d.dig("_npmUser", "name") } + end + + sig { returns(T.nilable(Source)) } + def find_source_from_registry + # Attempt to use version_listing first, as fetching the entire listing + # array can be slow (if it's large) + potential_sources = + [ + get_source(latest_version_listing["repository"]), + get_source(latest_version_listing["homepage"]), + get_source(latest_version_listing["bugs"]) + ].compact + + return potential_sources.first if potential_sources.any? + + potential_sources = + all_version_listings.flat_map do |_, listing| + [ + get_source(listing["repository"]), + get_source(listing["homepage"]), + get_source(listing["bugs"]) + ] + end.compact + + potential_sources.first + end + + sig { returns(T.nilable(Dependabot::DependencyRequirement::ObjectHash)) } + def new_source + sources = dependency.requirements + .map(&:source_hash).uniq.compact + .sort_by { |source| Package::RegistryFinder.central_registry?(T.cast(source[:url], String)) ? 1 : 0 } + + sources.first + end + + sig { params(details: T.nilable(T.any(String, T::Hash[String, String]))).returns(T.nilable(Source)) } + def get_source(details) + potential_url = get_url(details) + return unless potential_url + + potential_source = Source.from_url(potential_url) + return unless potential_source + + potential_source.directory = get_directory(details) + potential_source + end + + sig do + params( + details: T.nilable(T.any(String, T::Array[String], T::Hash[String, String])) + ).returns(T.nilable(String)) + end + def get_url(details) + return unless details + + url = + case details + when String then details + when Hash then details.fetch("url", nil) + when Array + # Try to find the first valid URL string, and if not, return the first string (even if it isn't a URL) + details.find { |d| d.is_a?(String) && d.match?(%r{^[\w.-]+/[\w.-]+$}) } || + details.find { |d| d.is_a?(String) } + end + return url unless url&.match?(%r{^[\w.-]+/[\w.-]+$}) + + "https://github.com/" + url + end + + sig { params(details: T.nilable(T.any(String, T::Hash[String, String]))).returns(T.nilable(String)) } + def get_directory(details) + # Only return a directory if it is explicitly specified + return unless details.is_a?(Hash) + + details.fetch("directory", nil) + end + + sig { returns(T.nilable(Source)) } + def find_source_from_git_url + url = new_source&.[](:url) || new_source&.fetch("url") + Source.from_url(T.cast(url, T.nilable(String))) + end + + sig { returns(T::Hash[String, T.untyped]) } + def latest_version_listing + return @latest_version_listing unless @latest_version_listing.nil? + + response = Dependabot::RegistryClient.get( + url: "#{dependency_url}/latest", + headers: registry_auth_headers + ) + return @latest_version_listing = {} if response.status >= 500 + + begin + @latest_version_listing = JSON.parse(response.body) + rescue JSON::ParserError + raise unless non_standard_registry? + + @latest_version_listing = {} + end + rescue JSON::ParserError, Excon::Error::Timeout + @latest_version_listing = T.let({}, T.nilable(T::Hash[String, T.untyped])) + end + + sig { returns(T::Array[[String, T::Hash[String, T.untyped]]]) } + def all_version_listings + return [] if npm_listing["versions"].nil? + + npm_listing["versions"] + .reject { |_, details| details["deprecated"] } + .sort_by { |version, _| Nub::Version.new(version) } + .reverse + end + + sig { returns(T::Hash[String, T.untyped]) } + def npm_listing + return @npm_listing unless @npm_listing.nil? + + response = Dependabot::RegistryClient.get(url: dependency_url, headers: registry_auth_headers) + return @npm_listing = {} if response.status >= 500 + + begin + @npm_listing = JSON.parse(response.body) + rescue JSON::ParserError + raise unless non_standard_registry? + + @npm_listing = {} + end + rescue Excon::Error::Timeout + @npm_listing = T.let({}, T.nilable(T::Hash[String, T.untyped])) + end + + sig { returns(String) } + def dependency_url + registry_url = + if new_source.nil? + configured_registry_from_credentials || "https://registry.npmjs.org" + else + new_source&.fetch(:url) + end + + # Remove trailing slashes and escape spaces for proper URL formatting + registry_url = URI::DEFAULT_PARSER.escape(registry_url)&.gsub(%r{/+$}, "") + + # NPM registries expect slashes to be escaped + escaped_dependency_name = dependency.name.gsub("/", "%2F") + "#{registry_url}/#{escaped_dependency_name}" + end + + sig { returns(T.nilable(String)) } + def configured_registry_from_credentials + # Look for a credential that replaces the base registry (global registry replacement) + replaces_base_cred = credentials.find { |cred| cred["type"] == "npm_registry" && cred.replaces_base? } + return normalize_registry_url(replaces_base_cred["registry"]) if replaces_base_cred + + nil + end + + sig { params(registry: T.nilable(String)).returns(T.nilable(String)) } + def normalize_registry_url(registry) + return nil unless registry + return registry if registry.start_with?("http") + + "https://#{registry}" + end + + sig { returns(T::Hash[String, String]) } + def registry_auth_headers + return {} unless auth_token + + { "Authorization" => "Bearer #{auth_token}" } + end + + sig { returns(String) } + def dependency_registry + source = new_source + return "registry.npmjs.org" if source.nil? + + T.cast(source.fetch(:url), String).gsub("https://", "").gsub("http://", "") + end + + sig { returns(T.nilable(String)) } + def auth_token + credentials + .select { |cred| cred["type"] == "npm_registry" } + .find { |cred| cred["registry"] == dependency_registry } + &.fetch("token", nil) + end + + sig { returns(T::Boolean) } + def non_standard_registry? + dependency_registry != "registry.npmjs.org" + end + end + end +end + +Dependabot::MetadataFinders + .register("nub", Dependabot::Nub::MetadataFinder) diff --git a/nub/lib/dependabot/nub/native_helpers.rb b/nub/lib/dependabot/nub/native_helpers.rb new file mode 100644 index 00000000000..18702bc159a --- /dev/null +++ b/nub/lib/dependabot/nub/native_helpers.rb @@ -0,0 +1,25 @@ +# typed: strong +# frozen_string_literal: true + +require "sorbet-runtime" + +module Dependabot + module Nub + module NativeHelpers + extend T::Sig + + sig { returns(String) } + def self.helper_path + "node #{File.join(native_helpers_root, 'run.js')}" + end + + sig { returns(String) } + def self.native_helpers_root + helpers_root = ENV.fetch("DEPENDABOT_NATIVE_HELPERS_PATH", nil) + return File.join(helpers_root, "nub") unless helpers_root.nil? + + File.join(__dir__, "../../../helpers") + end + end + end +end diff --git a/nub/lib/dependabot/nub/nub_package_manager.rb b/nub/lib/dependabot/nub/nub_package_manager.rb new file mode 100644 index 00000000000..4a2870bb853 --- /dev/null +++ b/nub/lib/dependabot/nub/nub_package_manager.rb @@ -0,0 +1,50 @@ +# typed: strong +# frozen_string_literal: true + +module Dependabot + module Nub + class NubPackageManager < Ecosystem::VersionManager + extend T::Sig + + NAME = "nub" + LOCKFILE_NAME = "nub.lock" + RC_FILENAME = ".npmrc" + + # nub writes `nub.lock`, which is byte-compatible with the pnpm lockfile v9 format + # (a rename-only transform of pnpm-lock.yaml). It is parsed via the shared pnpm parser. + # See https://github.com/nubjs/nub + # TODO: track nub's first release that stabilises `nub.lock`; 0.0.1 is a conservative floor. + MIN_SUPPORTED_VERSION = Version.new("0.0.1") + SUPPORTED_VERSIONS = T.let([MIN_SUPPORTED_VERSION].freeze, T::Array[Dependabot::Version]) + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::Nub::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end diff --git a/nub/lib/dependabot/nub/package/package_details_fetcher.rb b/nub/lib/dependabot/nub/package/package_details_fetcher.rb new file mode 100644 index 00000000000..4a74f70380b --- /dev/null +++ b/nub/lib/dependabot/nub/package/package_details_fetcher.rb @@ -0,0 +1,438 @@ +# typed: strict +# frozen_string_literal: true + +require "json" +require "excon" +require "time" +require "dependabot/package/package_release" +require "dependabot/package/package_details" +require "dependabot/nub/package/registry_finder" + +module Dependabot + module Nub + module Package + class PackageDetailsFetcher + extend T::Sig + + GLOBAL_REGISTRY = "registry.npmjs.org" + NPM_OFFICIAL_WEBSITE = "https://www.npmjs.com" + + API_AUTHORIZATION_KEY = "Authorization" + API_AUTHORIZATION_VALUE_BASIC_PREFIX = "Basic" + API_RESPONSE_STATUS_SUCCESS_PREFIX = "2" + + RELEASE_TIME_KEY = "time" + RELEASE_VERSIONS_KEY = "versions" + RELEASE_DIST_TAGS_KEY = "dist-tags" + RELEASE_DIST_TAGS_LATEST_KEY = "latest" + RELEASE_ENGINES_KEY = "engines" + RELEASE_LANGUAGE_KEY = "node" + RELEASE_DEPRECATION_KEY = "deprecated" + RELEASE_REPOSITORY_KEY = "repository" + RELEASE_PACKAGE_TYPE_KEY = "type" + RELEASE_PACKAGE_TYPE_GIT = "git" + RELEASE_PACKAGE_TYPE_NPM = "npm" + + REGISTRY_FILE_NPMRC = ".npmrc" + REGISTRY_FILE_YARNRC = ".yarnrc" + REGISTRY_FILE_YARNRC_YML = ".yarnrc.yml" + + sig do + params( + dependency: Dependabot::Dependency, + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential] + ).void + end + def initialize( + dependency:, + dependency_files:, + credentials: + ) + @dependency = dependency + @dependency_files = dependency_files + @credentials = credentials + + @npm_details = T.let(nil, T.nilable(T::Hash[String, T.untyped])) + @dist_tags = T.let(nil, T.nilable(T::Hash[String, String])) + @registry_finder = T.let(nil, T.nilable(Package::RegistryFinder)) + @version_endpoint_working = T.let(nil, T.nilable(T::Boolean)) + @yanked = T.let({}, T::Hash[Gem::Version, T.nilable(T::Boolean)]) + end + + sig { returns(Dependabot::Dependency) } + attr_reader :dependency + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T.nilable(Dependabot::Package::PackageDetails)) } + def fetch + package_data = npm_details + Dependabot::Package::PackageDetails.new( + dependency: @dependency, + releases: package_data ? parse_versions(package_data) : [], + dist_tags: dist_tags + ) + end + + sig { returns(T::Boolean) } + def valid_npm_details? + !dist_tags.nil? + end + + sig { returns(T.nilable(T::Hash[String, T.untyped])) } + def npm_details + @npm_details ||= fetch_npm_details + end + + sig { returns(T::Boolean) } + def custom_registry? + registry_finder.custom_registry? + end + + sig { returns(String) } + def dependency_url + registry_finder.dependency_url + end + + sig { params(version: Gem::Version).returns(T::Boolean) } + def yanked?(version) + return @yanked[version] || false if @yanked.key?(version) + + @yanked[version] = + begin + if dependency_registry == GLOBAL_REGISTRY + status = Dependabot::RegistryClient.head( + url: registry_finder.tarball_url(version), + headers: registry_auth_headers + ).status + else + status = Dependabot::RegistryClient.get( + url: dependency_url + "/#{version}", + headers: registry_auth_headers + ).status + + if status == 404 + # Some registries don't handle escaped package names properly + status = Dependabot::RegistryClient.get( + url: dependency_url.gsub("%2F", "/") + "/#{version}", + headers: registry_auth_headers + ).status + end + end + + version_not_found = status == 404 + version_not_found && version_endpoint_working? + rescue Excon::Error::Timeout, Excon::Error::Socket + # Give the benefit of the doubt if the registry is playing up + false + end + + @yanked[version] || false + end + + private + + sig { returns(T.nilable(T::Boolean)) } + def version_endpoint_working? + return true if dependency_registry == GLOBAL_REGISTRY + + return @version_endpoint_working if @version_endpoint_working + + @version_endpoint_working = + begin + Dependabot::RegistryClient.get( + url: dependency_url + "/#{RELEASE_DIST_TAGS_LATEST_KEY}", + headers: registry_auth_headers + ).status < 400 + rescue Excon::Error::Timeout, Excon::Error::Socket + # Give the benefit of the doubt if the registry is playing up + true + end + @version_endpoint_working + end + + sig do + params( + npm_data: T::Hash[String, T.untyped] + ).returns(T::Array[Dependabot::Package::PackageRelease]) + end + def parse_versions(npm_data) + time_data = fetch_value_from_hash(npm_data, RELEASE_TIME_KEY) || {} + versions_data = fetch_value_from_hash(npm_data, RELEASE_VERSIONS_KEY) || {} + + dist_tags = fetch_value_from_hash(npm_data, RELEASE_DIST_TAGS_KEY) + latest_version = fetch_value_from_hash(dist_tags, RELEASE_DIST_TAGS_LATEST_KEY) + + versions_data.filter_map do |version, details| + next unless Dependabot::Nub::Version.correct?(version) + + package_type = infer_package_type(details) + + Dependabot::Package::PackageRelease.new( + version: Version.new(version), + released_at: time_data[version] ? Time.parse(time_data[version]) : nil, + yanked: false, + yanked_reason: nil, + downloads: nil, + latest: latest_version.to_s == version, + url: package_version_url(version), + package_type: package_type, + language: package_language(details), + details: details + ) + end.sort_by(&:version).reverse + end + + sig { params(version: String).returns(String) } + def package_version_url(version) + "#{dependency_registry}/#{@dependency.name}/v/#{version}" + end + + sig do + params(version_details: T::Hash[String, T.untyped]) + .returns(T.nilable(Dependabot::Package::PackageLanguage)) + end + def package_language(version_details) + # Fetch the engines hash from the version details + engines = version_details.is_a?(Hash) ? version_details[RELEASE_ENGINES_KEY] : nil + # Check if engines is a hash and fetch the node requirement + node_requirement = engines.is_a?(Hash) ? engines.fetch(RELEASE_LANGUAGE_KEY, nil) : nil + + return nil unless node_requirement + + if node_requirement + Dependabot::Package::PackageLanguage.new( + name: RELEASE_LANGUAGE_KEY, + version: nil, + requirement: Requirement.new(node_requirement) + ) + end + rescue Gem::Requirement::BadRequirementError + nil + end + + sig { returns(T.nilable(T::Hash[String, String])) } + def dist_tags + @dist_tags ||= fetch_value_from_hash(npm_details, RELEASE_DIST_TAGS_KEY) + end + + sig { returns(T.nilable(T::Hash[String, T.untyped])) } + def fetch_npm_details + npm_response = fetch_npm_response + check_npm_response(npm_response) if npm_response + JSON.parse(npm_response.body) + rescue JSON::ParserError, Excon::Error::Timeout, Excon::Error::Socket, RegistryError => e + if git_dependency? + nil + else + raise_npm_details_error(e) + end + end + + sig { returns(Excon::Response) } + def fetch_npm_response + response = Dependabot::RegistryClient.get( + url: dependency_url, + headers: registry_auth_headers + ) + + # If response is successful, return it + return response if response.status.to_s.start_with?(API_RESPONSE_STATUS_SUCCESS_PREFIX) + + # If the registry is public (not explicitly private) and the request fails, return the response as is + return response if dependency_registry == GLOBAL_REGISTRY + + # If a private registry returns a 500 error, check authentication + return response unless response.status == 500 + + auth = fetch_value_from_hash(registry_auth_headers, API_AUTHORIZATION_KEY) + return response unless auth + + return response unless auth&.start_with?(API_AUTHORIZATION_VALUE_BASIC_PREFIX) + + decoded_token = Base64.decode64(auth.gsub("#{API_AUTHORIZATION_VALUE_BASIC_PREFIX} ", "")).strip + + # Ensure decoded token is not empty and contains a colon + if decoded_token.empty? || !decoded_token.include?(":") + raise PrivateSourceAuthenticationFailure, "Malformed basic auth credentials for #{dependency_registry}" + end + + username, password = decoded_token.split(":") + + Dependabot::RegistryClient.get( + url: dependency_url, + options: { + user: username, + password: password + } + ) + rescue URI::InvalidURIError => e + raise DependencyFileNotResolvable, e.message + end + + sig do + params( + details: T::Hash[String, T.untyped], + git_dependency: T::Boolean + ) + .returns(String) + end + def infer_package_type(details, git_dependency: false) + return RELEASE_PACKAGE_TYPE_GIT if git_dependency + + repository = fetch_value_from_hash(details, RELEASE_REPOSITORY_KEY) + + case repository + when String + return repository.start_with?("git+") ? RELEASE_PACKAGE_TYPE_GIT : RELEASE_PACKAGE_TYPE_NPM + when Hash + type = fetch_value_from_hash(repository, RELEASE_PACKAGE_TYPE_KEY) + return RELEASE_PACKAGE_TYPE_GIT if type == RELEASE_PACKAGE_TYPE_GIT + end + + RELEASE_PACKAGE_TYPE_NPM + end + + sig { params(npm_response: Excon::Response).void } + def check_npm_response(npm_response) + return if git_dependency? + + if private_dependency_not_reachable?(npm_response) + raise PrivateSourceAuthenticationFailure, dependency_registry + end + + # handles scenario when private registry returns a server error 5xx + if private_dependency_server_error?(npm_response) + msg = "Server error #{npm_response.status} returned while accessing registry" \ + " #{dependency_registry}." + raise DependencyFileNotResolvable, msg + end + + status = npm_response.status + + # handles issue when status 200 is returned from registry but with an invalid JSON object + if status.to_s.start_with?(API_RESPONSE_STATUS_SUCCESS_PREFIX) && response_invalid_json?(npm_response) + msg = "Invalid JSON object returned from registry #{dependency_registry}." + Dependabot.logger.warn("#{msg} Response body (truncated) : #{npm_response.body[0..500]}...") + raise DependencyFileNotResolvable, msg + end + + return if status.to_s.start_with?(API_RESPONSE_STATUS_SUCCESS_PREFIX) + + # Ignore 404s from the registry for updates where a lockfile doesn't + # need to be generated. The 404 won't cause problems later. + return if status == 404 && dependency.version.nil? + + msg = "Got #{status} response with body #{npm_response.body}" + raise RegistryError.new(status, msg) + end + + sig { params(error: StandardError).void } + def raise_npm_details_error(error) + raise if dependency_registry == GLOBAL_REGISTRY + raise unless error.is_a?(Excon::Error::Timeout) || error.is_a?(Excon::Error::Socket) + + raise PrivateSourceTimedOut, dependency_registry + end + + sig { params(npm_response: Excon::Response).returns(T::Boolean) } + def private_dependency_not_reachable?(npm_response) + return true if npm_response.body.start_with?(/user ".*?" is not a /) + return false unless [401, 402, 403, 404].include?(npm_response.status) + + # Check whether this dependency is (likely to be) private + if dependency_registry == GLOBAL_REGISTRY + return false unless dependency.name.start_with?("@") + + web_response = Dependabot::RegistryClient.get(url: "#{NPM_OFFICIAL_WEBSITE}/package/#{dependency.name}") + # NOTE: returns 429 when the login page is rate limited + return web_response.body.include?("Forgot password?") || + web_response.status == 429 + end + + true + end + + sig { params(npm_response: Excon::Response).returns(T::Boolean) } + def private_dependency_server_error?(npm_response) + if [500, 501, 502, 503].include?(npm_response.status) + Dependabot.logger.warn( + "#{dependency_registry} returned code #{npm_response.status} " \ + "with body #{npm_response.body}." + ) + return true + end + false + end + + sig { params(npm_response: Excon::Response).returns(T::Boolean) } + def response_invalid_json?(npm_response) + result = JSON.parse(npm_response.body) + result.is_a?(Hash) || result.is_a?(Array) + false + rescue JSON::ParserError, TypeError + true + end + + sig { returns(T::Hash[String, String]) } + def registry_auth_headers + registry_finder.auth_headers + end + + sig { returns(String) } + def dependency_registry + registry_finder.registry + end + + sig { returns(Package::RegistryFinder) } + def registry_finder + @registry_finder ||= Package::RegistryFinder.new( + dependency: dependency, + credentials: credentials, + npmrc_file: npmrc_file, + yarnrc_file: yarnrc_file, + yarnrc_yml_file: yarnrc_yml_file + ) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def npmrc_file + dependency_files.find { |f| f.name.end_with?(REGISTRY_FILE_NPMRC) } + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def yarnrc_file + dependency_files.find { |f| f.name.end_with?(REGISTRY_FILE_YARNRC) } + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def yarnrc_yml_file + dependency_files.find { |f| f.name.end_with?(REGISTRY_FILE_YARNRC_YML) } + end + + sig { returns(T::Boolean) } + def git_dependency? + # ignored_version/raise_on_ignored are irrelevant. + GitCommitChecker.new( + dependency: dependency, + credentials: credentials + ).git_dependency? + end + + # This function safely retrieves a value for a given key from a Hash. + # If the hash is valid and the key exists, it will return the value, otherwise nil. + sig { params(hash: T.untyped, key: T.untyped).returns(T.untyped) } + def fetch_value_from_hash(hash, key) + return nil unless hash.is_a?(Hash) # Return nil if the hash is not a Hash + + hash.fetch(key, nil) # Fetch the value for the given key, defaulting to nil if not found + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/package/registry_finder.rb b/nub/lib/dependabot/nub/package/registry_finder.rb new file mode 100644 index 00000000000..054dcce6939 --- /dev/null +++ b/nub/lib/dependabot/nub/package/registry_finder.rb @@ -0,0 +1,426 @@ +# typed: strict +# frozen_string_literal: true + +require "excon" +require "dependabot/nub/update_checker" +require "dependabot/registry_client" +require "sorbet-runtime" + +module Dependabot + module Nub + module Package + class RegistryFinder + extend T::Sig + + GLOBAL_NPM_REGISTRY = "https://registry.npmjs.org" + + CENTRAL_REGISTRIES = %w( + https://registry.npmjs.org + http://registry.npmjs.org + https://registry.yarnpkg.com + http://registry.yarnpkg.com + ).freeze + NPM_AUTH_TOKEN_REGEX = %r{//(?.*)/:_authToken=(?.*)$} + NPM_GLOBAL_REGISTRY_REGEX = /^registry\s*=\s*['"]?(?.*?)['"]?$/ + YARN_GLOBAL_REGISTRY_REGEX = /^(?:--)?registry\s+((['"](?.*)['"])|(?.*))/ + NPM_SCOPED_REGISTRY_REGEX = /^(?@[^:]+)\s*:registry\s*=\s*['"]?(?.*?)['"]?$/ + YARN_SCOPED_REGISTRY_REGEX = /['"](?@[^:]+):registry['"]\s((['"](?.*)['"])|(?.*))/ + + sig do + params( + dependency: T.nilable(Dependabot::Dependency), + credentials: T::Array[Dependabot::Credential], + npmrc_file: T.nilable(Dependabot::DependencyFile), + yarnrc_file: T.nilable(Dependabot::DependencyFile), + yarnrc_yml_file: T.nilable(Dependabot::DependencyFile) + ).void + end + def initialize( + dependency:, + credentials:, + npmrc_file: nil, + yarnrc_file: nil, + yarnrc_yml_file: nil + ) + @dependency = dependency + @credentials = credentials + @npmrc_file = npmrc_file + @yarnrc_file = yarnrc_file + @yarnrc_yml_file = yarnrc_yml_file + + @registry = T.let(nil, T.nilable(String)) + @first_registry_with_dependency_details = T.let(nil, T.nilable(String)) + @known_registries = T.let([], T::Array[T::Hash[String, T.nilable(String)]]) + @configured_global_registry = T.let(nil, T.nilable(String)) + @global_registry = T.let(nil, T.nilable(String)) + @parsed_yarnrc_yml = T.let(nil, T.nilable(T::Hash[String, T.untyped])) + end + + sig { returns(String) } + def registry + return @registry if @registry + + @registry = locked_registry || configured_registry || first_registry_with_dependency_details + T.must(@registry) + end + + sig { returns(T::Hash[String, String]) } + def auth_headers + auth_header_for(auth_token) + end + + sig { returns(String) } + def dependency_url + "#{registry_url}/#{escaped_dependency_name}" + end + + sig { params(version: T.any(String, Gem::Version)).returns(String) } + def tarball_url(version) + version_without_build_metadata = version.to_s.gsub(/\+.*/, "") + + # Dependency name needs to be unescaped since tarball URLs don't always work with escaped slashes + "#{registry_url}/#{dependency&.name}/-/#{scopeless_name}-#{version_without_build_metadata}.tgz" + end + + sig { params(registry: String).returns(T::Boolean) } + def self.central_registry?(registry) + CENTRAL_REGISTRIES.any? do |r| + r.include?(registry) + end + end + + sig { params(dependency_name: String).returns(T.nilable(String)) } + def registry_from_rc(dependency_name) + explicit_registry_from_rc(dependency_name) || global_registry + end + + sig { returns(T::Boolean) } + def custom_registry? + return false if CENTRAL_REGISTRIES.include?(registry_url) + + !(registry_url || "").match?(/registry\.npmjs\.(org|com)/) + end + + private + + sig { returns(T.nilable(Dependabot::Dependency)) } + attr_reader :dependency + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + attr_reader :npmrc_file + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + attr_reader :yarnrc_file + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + attr_reader :yarnrc_yml_file + + sig { params(dependency_name: T.nilable(String)).returns(T.nilable(String)) } + def explicit_registry_from_rc(dependency_name) + if dependency_name&.start_with?("@") && dependency_name.include?("/") + scope = dependency_name.split("/").first + scoped_registry(T.must(scope)) || configured_global_registry + else + configured_global_registry + end + end + + sig { returns(T.nilable(String)) } + def first_registry_with_dependency_details + return @first_registry_with_dependency_details if @first_registry_with_dependency_details + + @first_registry_with_dependency_details ||= + known_registries.find do |details| + url = "#{details['registry']&.gsub(%r{/++$}, '')}/#{escaped_dependency_name}" + url = "https://#{url}" unless url.start_with?("http") + response = Dependabot::RegistryClient.get( + url: url, + headers: auth_header_for(details["token"]) + ) + response.status < 400 && JSON.parse(response.body) + rescue Excon::Error::Timeout, + Excon::Error::Socket, + JSON::ParserError + nil + rescue URI::InvalidURIError => e + raise DependencyFileNotResolvable, e.message + end&.fetch("registry") + + @first_registry_with_dependency_details ||= global_registry + .sub(%r{/++$}, "") + .sub(%r{^[^/]*+(?:/[^/]*+)*?//}, "") + end + + sig { returns(T.nilable(String)) } + def registry_url + url = + if registry.start_with?("http") + registry + else + protocol = + if registry_source_url + registry_source_url&.split("://")&.first + else + "https" + end + + "#{protocol}://#{registry}" + end + + url.gsub(%r{/++$}, "") + end + + sig { params(token: T.nilable(String)).returns(T::Hash[String, String]) } + def auth_header_for(token) + return {} unless token + + if token.include?(":") + encoded_token = Base64.encode64(token).delete("\n") + { "Authorization" => "Basic #{encoded_token}" } + elsif Base64.decode64(token).ascii_only? && + Base64.decode64(token).include?(":") + { "Authorization" => "Basic #{token.delete("\n")}" } + else + { "Authorization" => "Bearer #{token}" } + end + end + + sig { returns(T.nilable(String)) } + def auth_token + known_registries + .find { |cred| cred["registry"] == registry } + &.fetch("token", nil) + end + + sig { returns(T.nilable(String)) } + def locked_registry + return unless registry_source_url + + lockfile_registry = + registry_source_url + &.gsub("https://", "") + &.gsub("http://", "") + + if lockfile_registry + detailed_registry = + known_registries + .find { |h| h["registry"]&.include?(lockfile_registry) } + &.fetch("registry") + end + + detailed_registry || lockfile_registry + end + + sig { returns(T.nilable(String)) } + def configured_registry + configured_registry_url = explicit_registry_from_rc(dependency&.name) + return unless configured_registry_url + + normalize_configured_registry(configured_registry_url) + end + + sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def known_registries + return @known_registries if @known_registries.any? + + @known_registries = + begin + registries = [] + registries += credentials + .select { |cred| cred["type"] == "npm_registry" && cred["registry"] } + .tap { |arr| arr.each { |c| c["token"] ||= nil } } + registries += npmrc_registries + registries += yarnrc_registries + + unique_registries(registries) + end + @known_registries + end + + sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def npmrc_registries + return [] unless npmrc_file + + registries = [] + npmrc_file&.content&.scan(NPM_AUTH_TOKEN_REGEX) do + next if Regexp.last_match&.[](:registry)&.include?("${") + + registry = T.must(Regexp.last_match)[:registry] + token = T.must(Regexp.last_match)[:token]&.strip + + registries << { + "type" => "npm_registry", + "registry" => registry&.gsub(/\s+/, "%20"), + "token" => token + } + end + + registries += npmrc_global_registries + end + + sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def yarnrc_registries + return [] unless yarnrc_file + + yarnrc_global_registries + end + + sig do + params(registries: T::Array[T::Hash[String, T.nilable(String)]]) + .returns(T::Array[T::Hash[String, T.nilable(String)]]) + end + def unique_registries(registries) + registries.uniq.reject do |registry| + next if registry["token"] + + # Reject this entry if an identical one with a token exists + registries.any? do |r| + r["token"] && r["registry"] == registry["registry"] + end + end + end + + sig { returns(String) } + def global_registry + return @global_registry if @global_registry + + @global_registry = configured_global_registry || GLOBAL_NPM_REGISTRY + @global_registry + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { returns(T.nilable(String)) } + def configured_global_registry + return @configured_global_registry if @configured_global_registry + + @configured_global_registry = (npmrc_file && npmrc_global_registries.first&.fetch("url")) || + (yarnrc_file && yarnrc_global_registries.first&.fetch("url")) + return @configured_global_registry if @configured_global_registry + + if parsed_yarnrc_yml&.key?("npmRegistryServer") + return @configured_global_registry = T.must(parsed_yarnrc_yml)["npmRegistryServer"] + end + + replaces_base = credentials.find { |cred| cred["type"] == "npm_registry" && cred.replaces_base? } + if replaces_base + registry = replaces_base["registry"] + registry = "https://#{registry}" unless registry&.start_with?("http") + return @configured_global_registry = registry + end + + @configured_global_registry = nil + end + # rubocop:enable Metrics/PerceivedComplexity + + sig { returns(T::Array[T::Hash[String, String]]) } + def npmrc_global_registries + global_rc_registries(npmrc_file, syntax: NPM_GLOBAL_REGISTRY_REGEX) + end + + sig { returns(T::Array[T::Hash[String, String]]) } + def yarnrc_global_registries + global_rc_registries(yarnrc_file, syntax: YARN_GLOBAL_REGISTRY_REGEX) + end + + sig { params(scope: String).returns(T.nilable(String)) } + def scoped_registry(scope) + scoped_rc_registry = scoped_rc_registry(npmrc_file, syntax: NPM_SCOPED_REGISTRY_REGEX, scope: scope) || + scoped_rc_registry(yarnrc_file, syntax: YARN_SCOPED_REGISTRY_REGEX, scope: scope) + return scoped_rc_registry if scoped_rc_registry + + if parsed_yarnrc_yml + yarn_berry_registry = parsed_yarnrc_yml&.dig("npmScopes", scope.delete_prefix("@"), "npmRegistryServer") + return yarn_berry_registry if yarn_berry_registry + end + + nil + end + + sig do + params( + file: T.nilable(Dependabot::DependencyFile), + syntax: T.any(String, Regexp) + ).returns(T::Array[T::Hash[String, String]]) + end + def global_rc_registries(file, syntax:) + registries = [] + + file&.content&.scan(syntax) do + next if Regexp.last_match&.[](:registry)&.include?("${") + + url = T.must(T.must(Regexp.last_match)[:registry]).strip + registry = normalize_configured_registry(url) + registries << { + "type" => "npm_registry", + "registry" => registry, + "url" => url, + "token" => nil + } + end + + registries + end + + sig do + params( + file: T.nilable(Dependabot::DependencyFile), + syntax: T.any(String, Regexp), + scope: String + ).returns(T.nilable(String)) + end + def scoped_rc_registry(file, syntax:, scope:) + file&.content.to_s.scan(syntax) do + next if Regexp.last_match&.[](:registry)&.include?("${") || Regexp.last_match&.[](:scope) != scope + + return T.must(T.must(Regexp.last_match)[:registry]).strip + end + + nil + end + + # npm registries expect slashes to be escaped + sig { returns(T.nilable(String)) } + def escaped_dependency_name + dependency&.name&.gsub("/", "%2F") + end + + sig { returns(T.nilable(String)) } + def scopeless_name + dependency&.name&.split("/")&.last + end + + sig { returns(T.nilable(String)) } + def registry_source_url # rubocop:disable Metrics/PerceivedComplexity + sources = dependency&.requirements + &.map(&:source_hash)&.uniq&.compact + &.sort_by { |source| self.class.central_registry?(T.cast(source[:url], String)) ? 1 : 0 } + + T.cast(sources&.find { |s| s[:type] == "registry" }&.fetch(:url), T.nilable(String)) + end + + sig { returns(T.nilable(T::Hash[String, T.untyped])) } + def parsed_yarnrc_yml + yarnrc_yml_file_content = yarnrc_yml_file&.content + return unless yarnrc_yml_file_content + return @parsed_yarnrc_yml if @parsed_yarnrc_yml + + @parsed_yarnrc_yml = YAML.safe_load(yarnrc_yml_file_content) + @parsed_yarnrc_yml + end + + # Possessive quantifiers and the explicit non-slash runs keep these linear + # on pathological input instead of backtracking polynomially. They match + # identically to the greedy forms for real registry URLs. + sig { params(url: String).returns(String) } + def normalize_configured_registry(url) + url.sub(%r{/++$}, "") + .sub(%r{^[^/]*+(?:/[^/]*+)*?//}, "") + .gsub(/\s+/, "%20") + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/package_manager.rb b/nub/lib/dependabot/nub/package_manager.rb new file mode 100644 index 00000000000..79faf8aed95 --- /dev/null +++ b/nub/lib/dependabot/nub/package_manager.rb @@ -0,0 +1,258 @@ +# typed: strict +# frozen_string_literal: true + +require "dependabot/shared_helpers" +require "dependabot/ecosystem" +require "dependabot/nub/requirement" +require "dependabot/nub/version_selector" +require "dependabot/nub/registry_helper" +require "dependabot/nub/nub_package_manager" +require "dependabot/nub/language" +require "dependabot/nub/constraint_helper" + +module Dependabot + module Nub + ECOSYSTEM = "nub" + MANIFEST_FILENAME = "package.json" + LERNA_JSON_FILENAME = "lerna.json" + PACKAGE_MANAGER_VERSION_REGEX = / + ^ # Start of string + (?\d+) # Major version (required, numeric) + \. # Separator between major and minor versions + (?\d+) # Minor version (required, numeric) + \. # Separator between minor and patch versions + (?\d+) # Patch version (required, numeric) + ( # Start pre-release section + -(?[a-zA-Z0-9.]+) # Pre-release label (optional, alphanumeric or dot-separated) + )? + ( # Start build metadata section + \+(?[a-zA-Z0-9.]+) # Build metadata (optional, alphanumeric or dot-separated) + )? + $ # End of string + /x # Extended mode for readability + + VALID_REQUIREMENT_CONSTRAINT = / + ^ # Start of string + (?=|>|>=|<|<=|~>|\\^) # Allowed operators + \s* # Optional whitespace + (?\d+) # Major version (required) + (\.(?\d+))? # Minor version (optional) + (\.(?\d+))? # Patch version (optional) + ( # Start pre-release section + -(?[a-zA-Z0-9.]+) # Pre-release label (optional) + )? + ( # Start build metadata section + \+(?[a-zA-Z0-9.]+) # Build metadata (optional) + )? + $ # End of string + /x # Extended mode for readability + + MANIFEST_PACKAGE_MANAGER_KEY = "packageManager" + MANIFEST_ENGINES_KEY = "engines" + + # Error malformed version number string + ERROR_MALFORMED_VERSION_NUMBER = "Malformed version number" + + class PackageManagerHelper + extend T::Sig + extend T::Helpers + + sig do + params( + package_json: T.nilable(T::Hash[String, T.untyped]), + lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)], + registry_config_files: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)], + credentials: T.nilable(T::Array[Dependabot::Credential]) + ).void + end + def initialize(package_json, lockfiles, registry_config_files, credentials) + @package_json = package_json + @lockfiles = lockfiles + @registry_helper = T.let( + RegistryHelper.new(registry_config_files, credentials), + Dependabot::Nub::RegistryHelper + ) + + @manifest_package_manager = T.let(package_json&.fetch(MANIFEST_PACKAGE_MANAGER_KEY, nil), T.nilable(String)) + @engines = T.let(package_json&.fetch(MANIFEST_ENGINES_KEY, nil), T.nilable(T::Hash[String, T.untyped])) + + @installed_versions = T.let({}, T::Hash[String, String]) + @registries = T.let({}, T::Hash[String, String]) + + @language = T.let(nil, T.nilable(Ecosystem::VersionManager)) + @language_requirement = T.let(nil, T.nilable(Requirement)) + end + + sig { returns(Ecosystem::VersionManager) } + def package_manager + package_manager_by_name(ECOSYSTEM) + end + + sig { returns(Ecosystem::VersionManager) } + def language + @language ||= Language.new( + raw_version: Helpers.node_version, + requirement: language_requirement + ) + end + + sig { returns(T.nilable(Requirement)) } + def language_requirement + @language_requirement ||= find_engine_constraints_as_requirement(Language::NAME) + end + + sig { params(name: String).returns(T.nilable(Requirement)) } + def find_engine_constraints_as_requirement(name) + Dependabot.logger.info("Processing engine constraints for #{name}") + + return nil unless @engines.is_a?(Hash) && @engines[name] + + raw_constraint = @engines[name].to_s.strip + return nil if raw_constraint.empty? + + constraints = ConstraintHelper.extract_ruby_constraints(raw_constraint) + # When constraints are invalid we return constraints array nil + if constraints.nil? + Dependabot.logger.warn( + "Unrecognized constraint format for #{name}: #{raw_constraint}" + ) + end + + if constraints && !constraints.empty? + Dependabot.logger.info("Parsed constraints for #{name}: #{constraints.join(', ')}") + Requirement.new(constraints) + end + rescue StandardError => e + Dependabot.logger.error("Error processing constraints for #{name}: #{e.message}") + nil + end + + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/PerceivedComplexity + sig { params(name: String).returns(T.nilable(T.any(Integer, String))) } + def setup(name) + # we prioritize version mentioned in "packageManager" instead of "engines" + # i.e. if { engines : "pnpm" : "6" } and { packageManager: "pnpm@6.0.2" }, + # we go for the specificity mentioned in packageManager (6.0.2) + + unless @manifest_package_manager&.start_with?("#{name}@") || + (@manifest_package_manager&.==name.to_s) || + @manifest_package_manager.nil? + return + end + + return package_manager.version.to_s if package_manager.deprecated? || package_manager.unsupported? + + if @engines && @manifest_package_manager.nil? + # if "packageManager" doesn't exists in manifest file, + # we check if we can extract "engines" information + version = check_engine_version(name) + + elsif @manifest_package_manager&.==name.to_s + # if "packageManager" is found but no version is specified (i.e. pnpm@1.2.3), + # we check if we can get "engines" info to override default version + version = check_engine_version(name) if @engines + + elsif @manifest_package_manager&.start_with?("#{name}@") + # if "packageManager" info has version specification i.e. yarn@3.3.1 + # we go with the version in "packageManager" + Dependabot.logger.info( + "Found \"#{MANIFEST_PACKAGE_MANAGER_KEY}\" : \"#{@manifest_package_manager}\". " \ + "Skipped checking \"#{MANIFEST_ENGINES_KEY}\"." + ) + end + + version ||= requested_version(name) + version ||= guessed_version(name) + + version + end + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + sig { params(name: String).returns(T.nilable(String)) } + def detect_version(name) + # Prioritize version mentioned in "packageManager" instead of "engines" + if @manifest_package_manager&.start_with?("#{name}@") + detected_version = @manifest_package_manager.split("@").last.to_s + end + + # If "packageManager" has no version specified, check if we can extract "engines" information + detected_version ||= check_engine_version(name) if detected_version.to_s.empty? + + # If neither "packageManager" nor "engines" have versions, infer version from lockfileVersion + detected_version ||= guessed_version(name) if detected_version.to_s.empty? + + # Strip and validate version format + detected_version_string = detected_version.to_s.strip + + # Ensure detected_version is neither "0" nor invalid format + return if detected_version_string == "0" || !detected_version_string.match?(ConstraintHelper::VERSION_REGEX) + + detected_version_string + end + + sig { params(name: String).returns(Ecosystem::VersionManager) } + def package_manager_by_name(name) + detected_version = detect_version(name) + + # if we have a detected version, we check if it is deprecated or unsupported + if detected_version + package_manager = NubPackageManager.new( + detected_version: detected_version.to_s + ) + return package_manager if package_manager.deprecated? || package_manager.unsupported? + end + + NubPackageManager.new( + detected_version: detected_version, + raw_version: installed_version + ) + end + + sig { returns(T.nilable(String)) } + def installed_version + Helpers.nub_version + end + + private + + sig { params(name: String).returns(T.nilable(String)) } + def requested_version(name) + return unless @manifest_package_manager + + match = @manifest_package_manager.match(/^#{name}@(?\d+.\d+.\d+)/) + return unless match + + Dependabot.logger.info("Requested version #{match['version']}") + match["version"] + end + + sig { params(name: String).returns(T.nilable(T.any(Integer, String))) } + def guessed_version(name) + lockfile = @lockfiles[name.to_sym] + return unless lockfile + + version = Helpers.send(:"#{name}_version_numeric", lockfile) + + Dependabot.logger.info("Guessed version info \"#{name}\" : \"#{version}\"") + + version + end + + sig { params(name: T.untyped).returns(T.nilable(String)) } + def check_engine_version(name) + return if @package_json.nil? + + version_selector = VersionSelector.new + + engine_versions = version_selector.setup(@package_json, name, NubPackageManager::SUPPORTED_VERSIONS) + + return if engine_versions.empty? + + version = engine_versions[name] + Dependabot.logger.info("Returned (#{MANIFEST_ENGINES_KEY}) info \"#{name}\" : \"#{version}\"") + version + end + end + end +end diff --git a/nub/lib/dependabot/nub/package_name.rb b/nub/lib/dependabot/nub/package_name.rb new file mode 100644 index 00000000000..a426f4ef1ff --- /dev/null +++ b/nub/lib/dependabot/nub/package_name.rb @@ -0,0 +1,12 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_name" + +# nub.lock is pnpm-lock v9; npm/pnpm package-naming rules are identical, so +# nub delegates to npm_and_yarn's PackageName rather than duplicating it. +module Dependabot + module Nub + PackageName = Dependabot::NpmAndYarn::PackageName + end +end diff --git a/nub/lib/dependabot/nub/pnpm_package_manager.rb b/nub/lib/dependabot/nub/pnpm_package_manager.rb new file mode 100644 index 00000000000..ce3e1b222c6 --- /dev/null +++ b/nub/lib/dependabot/nub/pnpm_package_manager.rb @@ -0,0 +1,59 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/nub/package_manager" + +module Dependabot + module Nub + class PNPMPackageManager < Ecosystem::VersionManager + extend T::Sig + + NAME = "pnpm" + LOCKFILE_NAME = "pnpm-lock.yaml" + PNPM_WS_YML_FILENAME = "pnpm-workspace.yaml" + + PNPM_V7 = "7" + PNPM_V8 = "8" + PNPM_V9 = "9" + + SUPPORTED_VERSIONS = T.let( + [ + Version.new(PNPM_V7), + Version.new(PNPM_V8), + Version.new(PNPM_V9) + ].freeze, + T::Array[Dependabot::Version] + ) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig do + params( + detected_version: T.nilable(String), + raw_version: T.nilable(String), + requirement: T.nilable(Dependabot::Nub::Requirement) + ).void + end + def initialize(detected_version: nil, raw_version: nil, requirement: nil) + super( + name: NAME, + detected_version: detected_version ? Version.new(detected_version) : nil, + version: raw_version ? Version.new(raw_version) : nil, + deprecated_versions: DEPRECATED_VERSIONS, + supported_versions: SUPPORTED_VERSIONS, + requirement: requirement + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + end +end diff --git a/nub/lib/dependabot/nub/registry_helper.rb b/nub/lib/dependabot/nub/registry_helper.rb new file mode 100644 index 00000000000..efc5d79cda1 --- /dev/null +++ b/nub/lib/dependabot/nub/registry_helper.rb @@ -0,0 +1,173 @@ +# typed: strict +# frozen_string_literal: true + +require "yaml" +require "dependabot/dependency_file" +require "sorbet-runtime" + +module Dependabot + module Nub + class RegistryHelper + extend T::Sig + + # Keys for configurations + REGISTRY_KEY = "registry" + AUTH_KEY = "authToken" + + # Yarn-specific keys + NPM_AUTH_TOKEN_KEY_FOR_YARN = "npmAuthToken" + NPM_SCOPE_KEY_FOR_YARN = "npmScopes" + NPM_REGISTER_KEY_FOR_YARN = "npmRegistryServer" + + sig do + params( + registry_config_files: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)], + credentials: T.nilable(T::Array[Dependabot::Credential]) + ).void + end + def initialize(registry_config_files, credentials) + @registry_config_files = registry_config_files + @credentials = credentials + end + + private + + sig { returns(T::Hash[Symbol, T.nilable(String)]) } + def find_registry_and_token + # Step 1: Check dependabot.yml configuration + dependabot_config = config_npm_registry_and_token + return dependabot_config if dependabot_config[:registry] + + # Step 2: Check .npmrc + npmrc_config = @registry_config_files[:npmrc] + npmrc_result = parse_registry_from_npmrc_yarnrc(npmrc_config, "=", "npm") + + return npmrc_result if npmrc_result[:registry] + + # Step 3: Check .yarnrc + yarnrc_config = @registry_config_files[:yarnrc] + yarnrc_result = parse_registry_from_npmrc_yarnrc(yarnrc_config, " ", "npm") + return yarnrc_result if yarnrc_result[:registry] + + # Step 4: Check yarnrc.yml + yarnrc_yml_config = @registry_config_files[:yarnrc_yml] + yarnrc_yml_result = parse_npm_from_yarnrc_yml(yarnrc_yml_config) + return yarnrc_yml_result if yarnrc_yml_result[:registry] + + # Default values if no registry is found + {} + end + + sig { returns(T::Hash[Symbol, T.nilable(String)]) } + def config_npm_registry_and_token + registries = {} + + return registries unless @credentials&.any? + + @credentials.each do |cred| + next unless cred["type"] == "npm_registry" # Skip if not an npm registry + next unless cred["replaces-base"] # Skip if not a reverse-proxy registry + + # Set the registry if it's not already set + registries[:registry] ||= cred["registry"] + + # Set the token if it's not already set + registries[:auth_token] ||= cred["token"] + end + registries + end + + # Find registry and token in .npmrc or .yarnrc file + sig do + params( + file: T.nilable(Dependabot::DependencyFile), + separator: String + ).returns(T::Hash[Symbol, T.nilable(String)]) + end + def parse_npm_from_npm_or_yarn_rc(file, separator = "=") + parse_registry_from_npmrc_yarnrc(file, separator, "npm") + end + + # Find registry and token in .npmrc or .yarnrc file + sig do + params( + file: T.nilable(Dependabot::DependencyFile), + separator: String, + scope: T.nilable(String) + ).returns(T::Hash[Symbol, T.nilable(String)]) + end + def parse_registry_from_npmrc_yarnrc(file, separator = "=", scope = nil) + content = file&.content + return { registry: nil, auth_token: nil } unless content + + global_registry = T.let(nil, T.nilable(String)) + scoped_registry = T.let(nil, T.nilable(String)) + auth_token = T.let(nil, T.nilable(String)) + + content.split("\n").each do |line| + # Split using the provided separator + key, value = line.strip.split(separator, 2) + next unless key && value + + # Remove surrounding quotes from keys and values + cleaned_key = key.strip.gsub(/\A["']|["']\z/, "") + cleaned_value = value.strip.gsub(/\A["']|["']\z/, "") + + case cleaned_key + when "registry" + # Case 1: Found a global registry + global_registry = cleaned_value + when "_authToken" + # Case 2: Found an auth token + auth_token = cleaned_value + else + # Handle scoped registry if a scope is provided + scoped_registry = cleaned_value if scope && cleaned_key == "@#{scope}:registry" + end + end + + # Determine the registry to return (global first, fallback to scoped) + registry = global_registry || scoped_registry + + { registry: registry, auth_token: auth_token } + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { params(file: T.nilable(Dependabot::DependencyFile)).returns(T::Hash[Symbol, T.nilable(String)]) } + def parse_npm_from_yarnrc_yml(file) + content = file&.content + return { registry: nil, auth_token: nil } unless content + + result = {} + yaml_data = safe_load_yaml(content) + + # Step 1: Extract global registry and auth token + result[:registry] = yaml_data[NPM_REGISTER_KEY_FOR_YARN] if yaml_data.key?(NPM_REGISTER_KEY_FOR_YARN) + result[:auth_token] = yaml_data[NPM_AUTH_TOKEN_KEY_FOR_YARN] if yaml_data.key?(NPM_AUTH_TOKEN_KEY_FOR_YARN) + + # Step 2: Fallback to any scoped registry and auth token if global is missing + if result[:registry].nil? && yaml_data.key?(NPM_SCOPE_KEY_FOR_YARN) + yaml_data[NPM_SCOPE_KEY_FOR_YARN].each do |_current_scope, config| + next unless config.is_a?(Hash) + + result[:registry] ||= config[NPM_REGISTER_KEY_FOR_YARN] + result[:auth_token] ||= config[NPM_AUTH_TOKEN_KEY_FOR_YARN] + end + end + + result + end + # rubocop:enable Metrics/PerceivedComplexity + + # Safely loads the YAML content and logs any parsing errors + sig { params(content: String).returns(T::Hash[String, T.untyped]) } + def safe_load_yaml(content) + YAML.safe_load(content, permitted_classes: [Symbol, String]) || {} + rescue Psych::SyntaxError => e + # Log the error instead of raising it + Dependabot.logger.error("YAML parsing error: #{e.message}") + {} + end + end + end +end diff --git a/nub/lib/dependabot/nub/registry_parser.rb b/nub/lib/dependabot/nub/registry_parser.rb new file mode 100644 index 00000000000..ca69dde6a69 --- /dev/null +++ b/nub/lib/dependabot/nub/registry_parser.rb @@ -0,0 +1,129 @@ +# typed: strict +# frozen_string_literal: true + +require "sorbet-runtime" + +module Dependabot + module Nub + class RegistryParser + # NOTE: npm_and_yarn has an equivalent implementation in + # npm_and_yarn/registry_parser.rb. Keep both in sync. + extend T::Sig + + sig { params(resolved_url: String, credentials: T::Array[Dependabot::Credential]).void } + def initialize(resolved_url:, credentials:) + @resolved_url = resolved_url + @credentials = credentials + end + + sig { params(name: String).returns(T::Hash[Symbol, T.untyped]) } + def registry_source_for(name) + url = + if resolved_url.include?("/~/") + # Gemfury format + resolved_url.split("/~/").first + elsif resolved_url.include?("/#{name}/-/#{name}") + # MyGet / Bintray format + T.must(resolved_url.split("/#{name}/-/#{name}").first) + .gsub("dl.bintray.com//", "api.bintray.com/npm/"). + # GitLab format + gsub(%r{\/projects\/\d+}, "") + elsif resolved_url.include?("/#{name}/-/#{name.split('/').last}") + # Sonatype Nexus / Artifactory JFrog format + resolved_url.split("/#{name}/-/#{name.split('/').last}").first + elsif (cred_url = url_for_relevant_cred) then cred_url + else + T.must(resolved_url.split("/")[0..2]).join("/") + end + + { type: "registry", url: url } + end + + sig { returns(String) } + def dependency_name + url_base = if resolved_url.include?("/-/") + T.must(resolved_url.split("/-/").first) + else + resolved_url + end + + package_name = url_base.gsub("%2F", "/").match(%r{@.*/}) + + return T.must(url_base.gsub("%2F", "/").split("/").last) unless package_name + + "#{package_name}#{T.must(url_base.gsub('%2F', '/').split('/').last)}" + end + + private + + sig { returns(String) } + attr_reader :resolved_url + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T.nilable(String)) } + def url_for_relevant_cred + resolved_uri = URI(resolved_url) + + credential_matching_url = + credentials + .select { |cred| cred["type"] == "npm_registry" && cred["registry"] } + .sort_by { |cred| cred.fetch("registry").length } + .find { |details| credential_matches?(details, resolved_uri: resolved_uri) } + + return unless credential_matching_url + + reg = credential_matching_url.fetch("registry") + # When the credential registry already includes an explicit scheme, return + # it directly — the gsub pattern would not match and would produce a + # malformed string if it ran. + return reg if reg.include?("://") + + build_registry_url(registry: reg, resolved_uri: resolved_uri) + end + + sig { params(registry: String, resolved_uri: URI::Generic).returns(String) } + def build_registry_url(registry:, resolved_uri:) + credential_uri = URI("https://#{registry}") + normalized_path = credential_uri.path.to_s.chomp("/") + + "#{resolved_uri.scheme}://#{resolved_uri.authority}#{normalized_path}" + end + + # Enforce npm registry credential boundaries by matching on host, optional + # explicit scheme, and full path segments so sibling paths on the same host + # cannot inherit credentials configured for a different registry scope. + sig { params(details: Dependabot::Credential, resolved_uri: URI::Generic).returns(T::Boolean) } + def credential_matches?(details, resolved_uri:) + resolved_url_host = resolved_uri.host + return true if resolved_url_host == details["registry"] + + registry_has_scheme = details["registry"]&.include?("://") + uri = if registry_has_scheme + URI(details.fetch("registry")) + else + URI("https://#{details['registry']}") + end + return false unless resolved_url_host == uri.host + # When the credential includes an explicit scheme, require scheme + # equality so we do not attribute a URL to credentials configured for + # a different transport protocol. + return false if registry_has_scheme && resolved_uri.scheme != uri.scheme + + # Use path-segment-aware matching to prevent credentials configured + # for one path-scoped registry from being applied to sibling paths + # on the same host (e.g., /victim-npm should not match /victim-npm-evil). + credential_path_match?(uri: uri, resolved_url_path: resolved_uri.path.to_s) + end + + sig { params(uri: URI::Generic, resolved_url_path: String).returns(T::Boolean) } + def credential_path_match?(uri:, resolved_url_path:) + registry_path = uri.path.to_s.chomp("/") + registry_path.empty? || + resolved_url_path.start_with?("#{registry_path}/") || + resolved_url_path == registry_path + end + end + end +end diff --git a/nub/lib/dependabot/nub/requirement.rb b/nub/lib/dependabot/nub/requirement.rb new file mode 100644 index 00000000000..fb6800b59ec --- /dev/null +++ b/nub/lib/dependabot/nub/requirement.rb @@ -0,0 +1,163 @@ +# typed: strict +# frozen_string_literal: true + +require "sorbet-runtime" + +require "dependabot/requirement" +require "dependabot/utils" +require "dependabot/nub/version" + +module Dependabot + module Nub + class Requirement < Dependabot::Requirement + extend T::Sig + + # Possessive quantifiers (++) keep this linear on pathological input rather + # than backtracking polynomially, and match identically to the greedy form + # for real requirement strings. + AND_SEPARATOR = /(?<=[a-zA-Z0-9*])\s++(?:&++\s++)?(?!\s*[|-])/ + OR_SEPARATOR = /(?<=[a-zA-Z0-9*])\s*\|+/ + + # Override the version pattern to allow a 'v' prefix + quoted = OPS.keys.map { |k| Regexp.quote(k) }.join("|") + version_pattern = "v?#{Nub::Version::VERSION_PATTERN}" + + PATTERN_RAW = T.let("\\s*(#{quoted})?\\s*(#{version_pattern})\\s*".freeze, String) + PATTERN = /\A#{PATTERN_RAW}\z/ + + sig do + params( + obj: T.any(String, Gem::Version) + ) + .returns(T::Array[T.any(String, T.nilable(Nub::Version))]) + end + def self.parse(obj) + return ["=", nil] if obj.is_a?(String) && Version::VERSION_TAGS.include?(obj.strip) + return ["=", Nub::Version.new(obj.to_s)] if obj.is_a?(Gem::Version) + + unless (matches = PATTERN.match(obj.to_s)) + msg = "Illformed requirement [#{obj.inspect}]" + raise BadRequirementError, msg + end + + return DefaultRequirement if matches[1] == ">=" && matches[2] == "0" + + [matches[1] || "=", Nub::Version.new(T.must(matches[2]))] + end + + # Returns an array of requirements. At least one requirement from the + # returned array must be satisfied for a version to be valid. + sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) } + def self.requirements_array(requirement_string) + return [new(nil)] if requirement_string.nil? + + # Removing parentheses is technically wrong but they are extremely + # rarely used. + # TODO: Handle complicated parenthesised requirements + requirement_string = requirement_string.gsub(/[()]/, "") + requirement_string.strip.split(OR_SEPARATOR).map do |req_string| + requirements = req_string.strip.split(AND_SEPARATOR) + new(requirements) + end + end + + sig { params(requirements: T.nilable(T.any(String, T::Array[String]))).void } + def initialize(*requirements) + requirements = requirements.flatten + .flat_map { |req_string| T.must(req_string).split(",").map(&:strip) } + .flat_map { |req_string| convert_js_constraint_to_ruby_constraint(req_string) } + + super(requirements) + end + + private + + sig { params(req_string: String).returns(T.any(String, T::Array[String])) } + def convert_js_constraint_to_ruby_constraint(req_string) + return req_string if req_string.match?(/^([A-Za-uw-z]|v[^\d])/) + + req_string = req_string.gsub(/(?:\.|^)[xX*]/, "") + + if req_string.empty? then ">= 0" + elsif req_string.start_with?("~>") then req_string + elsif req_string.start_with?("=") then req_string.gsub(/^=*/, "") + elsif req_string.start_with?("~") then convert_tilde_req(req_string) + elsif req_string.start_with?("^") then convert_caret_req(req_string) + elsif req_string.include?(" - ") then convert_hyphen_req(req_string) + elsif req_string.match?(/[<>]/) then req_string + else + ruby_range(req_string) + end + end + + sig { params(req_string: String).returns(String) } + def convert_tilde_req(req_string) + version = req_string.gsub(/^~\>?[\s=]*/, "") + parts = version.split(".") + parts << "0" if parts.count < 3 + "~> #{parts.join('.')}" + end + + sig { params(req_string: String).returns(T::Array[String]) } + def convert_hyphen_req(req_string) + parts = req_string.split(/\s+-\s+/) + lower_bound = T.must(parts[0]) + upper_bound = T.must(parts[1]) + lower_bound_parts = lower_bound.split(".") + lower_bound_parts.fill("0", lower_bound_parts.length...3) + + upper_bound_parts = upper_bound.split(".") + upper_bound_range = + if upper_bound_parts.length < 3 + # When upper bound is a partial version treat these as an X-range + upper_bound_parts[-1] = upper_bound_parts[-1].to_i + 1 if upper_bound_parts[-1].to_i.positive? + upper_bound_parts.fill("0", upper_bound_parts.length...3) + "< #{upper_bound_parts.join('.')}.a" + else + "<= #{upper_bound_parts.join('.')}" + end + + [">= #{lower_bound_parts.join('.')}", upper_bound_range] + end + + sig { params(req_string: String).returns(String) } + def ruby_range(req_string) + parts = req_string.split(".") + # If we have three or more parts then this is an exact match + return req_string if parts.count >= 3 + + # If we have fewer than three parts we do a partial match + parts << "0" + "~> #{parts.join('.')}" + end + + sig { params(req_string: String).returns(T::Array[String]) } + def convert_caret_req(req_string) + version = req_string.gsub(/^\^[\s=]*/, "") + parts = version.split(".") + parts.fill("x", parts.length...3) + first_non_zero = parts.find { |d| d != "0" } + first_non_zero_index = + first_non_zero ? T.must(parts.index(first_non_zero)) : parts.count - 1 + # If the requirement has a blank minor or patch version increment the + # previous index value with 1 + first_non_zero_index -= 1 if first_non_zero == "x" + upper_bound = parts.map.with_index do |part, i| + if i < first_non_zero_index then part + elsif i == first_non_zero_index then (part.to_i + 1).to_s + elsif i > first_non_zero_index && i == 2 then "0.a" + else + 0 + end + end.join(".") + + [">= #{version}", "< #{upper_bound}"] + end + end + end +end + +Dependabot::Utils.register_requirement_class( + "nub", + Dependabot::Nub::Requirement +) diff --git a/nub/lib/dependabot/nub/sub_dependency_files_filterer.rb b/nub/lib/dependabot/nub/sub_dependency_files_filterer.rb new file mode 100644 index 00000000000..268fde72719 --- /dev/null +++ b/nub/lib/dependabot/nub/sub_dependency_files_filterer.rb @@ -0,0 +1,82 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/utils" +require "dependabot/nub/version" +require "dependabot/nub/file_parser/lockfile_parser" +require "sorbet-runtime" + +# Used in the sub dependency version resolver and file updater to only run +# yarn/npm helpers on dependency files that require updates. This is useful for +# large monorepos with lots of sub-projects that don't all have the same +# dependencies. +module Dependabot + module Nub + class SubDependencyFilesFilterer + extend T::Sig + + sig { params(dependency_files: T::Array[DependencyFile], updated_dependencies: T::Array[Dependency]).void } + def initialize(dependency_files:, updated_dependencies:) + @dependency_files = dependency_files + @updated_dependencies = updated_dependencies + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def files_requiring_update + return T.must(@files_requiring_update) if defined? @files_requiring_update + + files_requiring_update = + lockfiles.select do |lockfile| + lockfile_dependencies(lockfile).any? do |sub_dep| + updated_dependencies.any? do |updated_dep| + next false unless sub_dep.name == updated_dep.name + + version_class.new(updated_dep.version) > + version_class.new(sub_dep.version) + end + end + end + + @files_requiring_update ||= T.let(files_requiring_update, T.nilable(T::Array[DependencyFile])) + end + + private + + sig { returns(T::Array[DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependency]) } + attr_reader :updated_dependencies + + sig { params(lockfile: DependencyFile).returns(T::Array[Dependabot::Dependency]) } + def lockfile_dependencies(lockfile) + @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]])) + @lockfile_dependencies[lockfile.name] ||= + Nub::FileParser::LockfileParser.new( + dependency_files: [lockfile] + ).parse + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def lockfiles + dependency_files.select { |file| lockfile?(file) } + end + + sig { params(file: DependencyFile).returns(T::Boolean) } + def lockfile?(file) + file.name.end_with?( + "package-lock.json", + "yarn.lock", + "npm-shrinkwrap.json", + "nub.lock", + "pnpm-lock.yaml" + ) + end + + sig { returns(T.class_of(Dependabot::Nub::Version)) } + def version_class + Nub::Version + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker.rb b/nub/lib/dependabot/nub/update_checker.rb new file mode 100644 index 00000000000..12ea4899290 --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker.rb @@ -0,0 +1,565 @@ +# typed: strict +# frozen_string_literal: true + +require "dependabot/git_commit_checker" +require "dependabot/requirements_update_strategy" +require "dependabot/shared_helpers" +require "dependabot/update_checkers" +require "dependabot/update_checkers/base" + +module Dependabot + module Nub + class UpdateChecker < Dependabot::UpdateCheckers::Base # rubocop:disable Metrics/ClassLength + extend T::Sig + + require_relative "update_checker/requirements_updater" + require_relative "update_checker/library_detector" + require_relative "update_checker/latest_version_finder" + require_relative "update_checker/version_resolver" + require_relative "update_checker/subdependency_version_resolver" + require_relative "update_checker/vulnerability_auditor" + + sig do + params( + dependency: Dependabot::Dependency, + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential], + repo_contents_path: T.nilable(String), + ignored_versions: T::Array[String], + raise_on_ignored: T::Boolean, + security_advisories: T::Array[Dependabot::SecurityAdvisory], + requirements_update_strategy: T.nilable(Dependabot::RequirementsUpdateStrategy), + dependency_group: T.nilable(Dependabot::DependencyGroup), + update_cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions), + options: T::Hash[Symbol, T.untyped] + ) + .void + end + def initialize( # rubocop:disable Metrics/AbcSize + dependency:, + dependency_files:, + credentials:, + repo_contents_path: nil, + ignored_versions: [], + raise_on_ignored: false, + security_advisories: [], + requirements_update_strategy: nil, + dependency_group: nil, + update_cooldown: nil, + options: {} + ) + @latest_version = T.let(nil, T.nilable(T.any(String, Gem::Version))) + @latest_resolvable_version = T.let(nil, T.nilable(T.any(String, Dependabot::Version))) + @updated_requirements = T.let(nil, T.nilable(T::Array[Dependabot::DependencyRequirement])) + @vulnerability_audit = T.let(nil, T.nilable(T::Hash[String, T.untyped])) + @vulnerable_versions = T.let(nil, T.nilable(T::Array[T.any(String, Gem::Version)])) + + @latest_version_for_git_dependency = T.let(nil, T.nilable(T.any(String, Gem::Version))) + @latest_released_version = T.let(nil, T.nilable(Gem::Version)) + @latest_version_details = T.let(nil, T.nilable(T::Hash[Symbol, T.untyped])) + @latest_version_finder = T.let(nil, T.nilable(PackageLatestVersionFinder)) + @version_resolver = T.let(nil, T.nilable(VersionResolver)) + @subdependency_version_resolver = T.let(nil, T.nilable(SubdependencyVersionResolver)) + @library = T.let(nil, T.nilable(T::Boolean)) + @package_json = T.let(nil, T.nilable(Dependabot::DependencyFile)) + @git_commit_checker = T.let(nil, T.nilable(Dependabot::GitCommitChecker)) + super + end + + sig { returns(T::Boolean) } + def up_to_date? + return false if security_update? && + dependency.version && + version_class.correct?(dependency.version) && + vulnerable_versions.any? && + !vulnerable_versions.include?(current_version) + + super + end + + sig { returns(T::Boolean) } + def vulnerable? + super || vulnerable_versions.any? + end + + sig { override.returns(T.nilable(T.any(String, Gem::Version))) } + def latest_version + @latest_version ||= + if git_dependency? + latest_version_for_git_dependency + else + latest_version_details&.fetch(:version) + end + end + + sig { override.returns(T.nilable(T.any(String, Gem::Version))) } + def latest_resolvable_version + return unless latest_version + + @latest_resolvable_version ||= + if dependency.top_level? + T.cast( + version_resolver.latest_resolvable_version, + T.nilable(T.any(String, Dependabot::Version)) + ) + else + # If the dependency is indirect its version is constrained by the + # requirements placed on it by dependencies lower down the tree + T.cast( + subdependency_version_resolver.latest_resolvable_version, + T.nilable(T.any(String, Dependabot::Version)) + ) + end + end + + sig { override.returns(T.nilable(Dependabot::Version)) } + def lowest_security_fix_version + # This will require a full unlock to update multiple top level ancestors. + return if vulnerability_audit["fix_available"] && vulnerability_audit["top_level_ancestors"].count > 1 + + T.unsafe(latest_version_finder.lowest_security_fix_version) + end + + sig { override.returns(T.nilable(Dependabot::Version)) } + def lowest_resolvable_security_fix_version + raise "Dependency not vulnerable!" unless vulnerable? + + # NOTE: Currently, we don't resolve transitive/sub-dependencies as + # npm/yarn don't provide any control over updating to a specific + # sub-dependency version. + + # Return nil for vulnerable transitive dependencies if there are conflicting dependencies. + # This helps catch errors in such cases. + return nil if !dependency.top_level? && conflicting_dependencies.any? + + # For transitive dependencies without conflicts, return the latest resolvable transitive + # security fix version that does not require unlocking other dependencies. + return latest_resolvable_transitive_security_fix_version_with_no_unlock unless dependency.top_level? + + # For top-level dependencies, return the lowest security fix version. + # TODO: Consider checking resolvability here in the future. + lowest_security_fix_version + end + + sig { override.returns(T.nilable(T.any(String, Dependabot::Version))) } + def latest_resolvable_version_with_no_unlock + unless dependency.top_level? + return T.cast(latest_resolvable_version, T.nilable(T.any(String, Dependabot::Version))) + end + + return latest_resolvable_version_with_no_unlock_for_git_dependency if git_dependency? + + latest_version_finder.latest_version_with_no_unlock + end + + sig do + params(updated_version: T.any(String, Gem::Version)) + .returns(T.nilable(T.any(String, T.untyped))) + end + def latest_resolvable_previous_version(updated_version) + T.unsafe(version_resolver.latest_resolvable_previous_version(updated_version)) + end + + sig { override.returns(T::Array[Dependabot::DependencyRequirement]) } + def updated_requirements + resolvable_version = + if preferred_resolvable_version.is_a?(version_class) + preferred_resolvable_version.to_s + elsif preferred_resolvable_version.nil? + nil + else + # If the preferred_resolvable_version came back as anything other + # than a version class or `nil` it must be because this is a git + # dependency, for which we don't check resolvability. + latest_version_details&.fetch(:version, nil)&.to_s + end + + @updated_requirements ||= + RequirementsUpdater.new( + requirements: dependency.requirements, + updated_source: updated_source, + latest_resolvable_version: resolvable_version, + update_strategy: T.must(requirements_update_strategy) + ).updated_requirements + end + + sig { returns(T::Boolean) } + def requirements_unlocked_or_can_be? + !requirements_update_strategy&.lockfile_only? + end + + sig { returns(T.nilable(Dependabot::RequirementsUpdateStrategy)) } + def requirements_update_strategy + # If passed in as an option (in the base class) honour that option + return @requirements_update_strategy if @requirements_update_strategy + + # Otherwise, widen ranges for libraries and bump versions for apps + library? ? RequirementsUpdateStrategy::WidenRanges : RequirementsUpdateStrategy::BumpVersions + end + + sig { override.returns(T::Array[T::Hash[String, String]]) } + def conflicting_dependencies + # The inherited yarn-based ConflictingDependencyResolver was inert for nub: DependencyFilesBuilder + # only ever writes nub.lock while the yarn helper reads yarn.lock, so every call failed into a + # rescue -> []. The live signal is the vulnerability audit's unfixable-conflict explanation; + # pnpm-lock-aware conflict detection over nub.lock is a follow-up. + return [] unless vulnerability_audit_performed? + + [vulnerability_audit].select do |hash| + !hash["fix_available"] && hash["explanation"] + end + end + + private + + sig { returns(T::Boolean) } + def vulnerability_audit_performed? + !!defined?(@vulnerability_audit) + end + + sig { returns(T::Hash[String, T.untyped]) } + def vulnerability_audit + @vulnerability_audit ||= + VulnerabilityAuditor.new( + dependency_files: dependency_files, + credentials: credentials + ).audit( + dependency: dependency, + security_advisories: security_advisories + ) + end + + sig { returns(T::Array[T.any(String, Gem::Version)]) } + def vulnerable_versions + @vulnerable_versions ||= + begin + all_versions = dependency.all_versions + .filter_map { |v| version_class.new(v) if version_class.correct?(v) } + + all_versions.select do |v| + security_advisories.any? { |advisory| advisory.vulnerable?(v) } + end + end + end + + sig { override.returns(T::Boolean) } + def latest_version_resolvable_with_full_unlock? + return false unless latest_version + + return version_resolver.latest_version_resolvable_with_full_unlock? if dependency.top_level? + + return false unless security_advisories.any? + + vulnerability_audit["fix_available"] + end + + sig { override.returns(T::Array[Dependabot::Dependency]) } + def updated_dependencies_after_full_unlock + return conflicting_updated_dependencies if security_advisories.any? && vulnerability_audit["fix_available"] + + T.must(version_resolver.dependency_updates_from_full_unlock) + .map { |update_details| build_updated_dependency(update_details.transform_keys(&:to_sym)) } + end + + # rubocop:disable Metrics/AbcSize + sig { returns(T::Array[Dependabot::Dependency]) } + def conflicting_updated_dependencies + top_level_dependencies = top_level_dependency_lookup + + updated_deps = [] + vulnerability_audit["fix_updates"].each do |update| + dependency_name = update["dependency_name"] + requirements = top_level_dependencies[dependency_name]&.requirements || [] + + updated_deps << build_updated_dependency( + dependency: Dependency.new( + name: dependency_name, + package_manager: "nub", + requirements: requirements + ), + version: update["target_version"], + previous_version: update["current_version"] + ) + end + # rubocop:enable Metrics/AbcSize + + # We don't need to directly update the target dependency if it will + # be updated as a side effect of updating the parent. However, we need + # to include it so it's described in the PR and we'll pass validation + # that this dependency is at a non-vulnerable version. + if updated_deps.none? { |dep| dep.name == dependency.name } + target_version = vulnerability_audit["target_version"] + updated_deps << build_updated_dependency( + dependency: dependency, + version: target_version, + previous_version: dependency.version, + removed: target_version.nil?, + metadata: { information_only: true } # Instruct updater to not directly update this dependency + ) + end + + # Target dependency should be first in the result to support rebases + updated_deps.select { |dep| dep.name == dependency.name } + + updated_deps.reject { |dep| dep.name == dependency.name } + end + + sig { returns(T::Hash[String, Dependabot::Dependency]) } + def top_level_dependency_lookup + top_level_dependencies = FileParser.new( + dependency_files: dependency_files, + credentials: credentials, + source: nil + ).parse.select(&:top_level?) + + top_level_dependencies.to_h { |dep| [dep.name, dep] } + end + + sig do + params( + update_details: T::Hash[Symbol, T.untyped] + ).returns(Dependabot::Dependency) + end + def build_updated_dependency(update_details) + original_dep = update_details.fetch(:dependency) + removed = update_details.fetch(:removed, false) + version = update_details.fetch(:version).to_s unless removed + previous_version = update_details.fetch(:previous_version)&.to_s + metadata = update_details.fetch(:metadata, {}) + + Dependency.new( + name: original_dep.name, + version: version, + requirements: RequirementsUpdater.new( + requirements: original_dep.requirements, + updated_source: original_dep == dependency ? updated_source : original_source(original_dep), + latest_resolvable_version: version, + update_strategy: T.must(requirements_update_strategy) + ).updated_requirements, + previous_version: previous_version, + previous_requirements: original_dep.requirements, + package_manager: original_dep.package_manager, + removed: removed, + metadata: metadata + ) + end + + sig { returns(T.nilable(T.any(String, Gem::Version, T.untyped))) } + def latest_resolvable_transitive_security_fix_version_with_no_unlock + versions = T.let([], T::Array[Gem::Version]) + + latest = latest_released_version + versions.push(latest) if latest + + fix_possible = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions( + versions, + security_advisories + ).any? + return nil unless fix_possible + + latest_resolvable_version + end + + sig { returns(T.nilable(T.any(String, Dependabot::Version))) } + def latest_resolvable_version_with_no_unlock_for_git_dependency + reqs = dependency.requirements.filter_map do |r| + requirement = r.requirement_string + next if requirement.nil? + + requirement_class.requirements_array(requirement) + end + + current_version = + if existing_version_is_sha? || + !version_class.correct?(dependency.version) + dependency.version + else + version_class.new(dependency.version) + end + + return current_version if git_commit_checker.pinned? + + # TODO: Really we should get a tag that satisfies the semver req + return current_version if reqs.any? + + git_commit_checker.head_commit_for_current_branch + end + + sig { returns(T.nilable(T.any(String, Gem::Version))) } + def latest_version_for_git_dependency + @latest_version_for_git_dependency ||= + if version_class.correct?(dependency.version) + T.unsafe( + latest_git_version_details[:version] && + version_class.new(latest_git_version_details[:version]) + ) + else + latest_git_version_details[:sha] + end + end + + sig { returns(T.nilable(Gem::Version)) } + def latest_released_version + @latest_released_version ||= + latest_version_finder.latest_version_from_registry + end + + sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) } + def latest_version_details + @latest_version_details ||= + if git_dependency? + latest_git_version_details + else + { version: latest_released_version } + end + end + + sig { returns(PackageLatestVersionFinder) } + def latest_version_finder + @latest_version_finder ||= PackageLatestVersionFinder.new( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + raise_on_ignored: raise_on_ignored, + security_advisories: security_advisories, + cooldown_options: @update_cooldown + ) + end + + sig { returns(VersionResolver) } + def version_resolver + @version_resolver ||= + VersionResolver.new( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + latest_allowable_version: latest_version, + latest_version_finder: latest_version_finder, + repo_contents_path: repo_contents_path, + dependency_group: dependency_group, + raise_on_ignored: raise_on_ignored, + update_cooldown: @update_cooldown + ) + end + + sig { returns(SubdependencyVersionResolver) } + def subdependency_version_resolver + @subdependency_version_resolver ||= + SubdependencyVersionResolver.new( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + latest_allowable_version: latest_version, + repo_contents_path: repo_contents_path + ) + end + + sig { returns(T::Boolean) } + def git_dependency? + git_commit_checker.git_dependency? + end + + sig { returns(T::Hash[Symbol, T.untyped]) } + def latest_git_version_details + semver_req = + dependency.requirements + .find { |req| req.source_string("type") == "git" } + &.requirement_string + + # If there was a semver requirement provided or the dependency was + # pinned to a version, look for the latest tag + if semver_req || git_commit_checker.pinned_ref_looks_like_version? + latest_tag = git_commit_checker.local_tag_for_latest_version(update_cooldown) + return { + sha: latest_tag&.commit_sha, + version: latest_tag&.tag&.gsub(/^[^\d]*/, "") + } + end + + # Otherwise, if the gem isn't pinned, the latest version is just the + # latest commit for the specified branch. + return { sha: git_commit_checker.head_commit_for_current_branch } unless git_commit_checker.pinned? + + # If the dependency is pinned to a tag that doesn't look like a + # version then there's nothing we can do. + { sha: dependency.version } + end + + sig { returns(T.nilable(Dependabot::DependencyRequirement::ObjectHash)) } + def updated_source + # Never need to update source, unless a git_dependency + return dependency_source_details unless git_dependency? + + # Update the git tag if updating a pinned version + if git_commit_checker.pinned_ref_looks_like_version? && + !git_commit_checker.local_tag_for_latest_version(update_cooldown).nil? + new_tag = git_commit_checker.local_tag_for_latest_version(update_cooldown) + return dependency_source_details&.merge(ref: new_tag&.tag) + end + + # Otherwise return the original source + dependency_source_details + end + + sig { returns(T::Boolean) } + def library? + return true unless dependency.version + return true if dependency_files.any? { |f| f.name == "lerna.json" } + + @library = + LibraryDetector.new( + package_json_file: T.must(package_json), + credentials: credentials, + dependency_files: dependency_files + ).library? + end + + sig { returns(T::Boolean) } + def security_update? + security_advisories.any? + end + + sig { returns(T.nilable(Dependabot::DependencyRequirement::ObjectHash)) } + def dependency_source_details + original_source(dependency) + end + + sig do + params(updated_dependency: Dependabot::Dependency) + .returns(T.nilable(Dependabot::DependencyRequirement::ObjectHash)) + end + def original_source(updated_dependency) + sources = + updated_dependency + .requirements.map(&:source_hash) + .uniq.compact + .sort_by do |source| + Package::RegistryFinder.central_registry?(T.cast(source[:url], String)) ? 1 : 0 + end + + sources.first + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def package_json + @package_json ||= + dependency_files.find { |f| f.name == "package.json" } + end + + sig { returns(Dependabot::GitCommitChecker) } + def git_commit_checker + @git_commit_checker ||= + GitCommitChecker.new( + dependency: dependency, + credentials: credentials, + ignored_versions: ignored_versions, + raise_on_ignored: raise_on_ignored + ) + end + end + end +end + +Dependabot::UpdateCheckers + .register("nub", Dependabot::Nub::UpdateChecker) diff --git a/nub/lib/dependabot/nub/update_checker/dependency_files_builder.rb b/nub/lib/dependabot/nub/update_checker/dependency_files_builder.rb new file mode 100644 index 00000000000..3b64b1f2fb5 --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/dependency_files_builder.rb @@ -0,0 +1,110 @@ +# typed: strong +# frozen_string_literal: true + +require "sorbet-runtime" + +require "dependabot/nub/file_updater/npmrc_builder" +require "dependabot/nub/file_updater/package_json_preparer" + +module Dependabot + module Nub + class UpdateChecker + class DependencyFilesBuilder + extend T::Sig + + sig do + params( + dependency: Dependabot::Dependency, + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential] + ) + .void + end + def initialize(dependency:, dependency_files:, credentials:) + @dependency = dependency + @dependency_files = dependency_files + @credentials = credentials + end + + sig { void } + def write_temporary_dependency_files + write_lockfiles + + File.write(".npmrc", npmrc_content) + + package_files.each do |file| + path = file.name + FileUtils.mkdir_p(Pathname.new(path).dirname) + File.write(file.name, prepared_package_json_content(file)) + end + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def nub_locks + @nub_locks ||= T.let( + dependency_files + .select { |f| f.name.end_with?("nub.lock") }, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def root_nub_lock + @root_nub_lock ||= T.let( + dependency_files + .find { |f| f.name == "nub.lock" }, + T.nilable(Dependabot::DependencyFile) + ) + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def lockfiles + [*nub_locks] + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def package_files + @package_files ||= T.let( + dependency_files + .select { |f| f.name.end_with?("package.json") }, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) + end + + private + + sig { returns(Dependabot::Dependency) } + attr_reader :dependency + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { void } + def write_lockfiles + nub_locks.each do |f| + FileUtils.mkdir_p(Pathname.new(f.name).dirname) + File.write(f.name, f.content) + end + end + + sig { params(file: Dependabot::DependencyFile).returns(String) } + def prepared_package_json_content(file) + Nub::FileUpdater::PackageJsonPreparer.new( + package_json_content: T.must(file.content) + ).prepared_content + end + + sig { returns(String) } + def npmrc_content + Nub::FileUpdater::NpmrcBuilder.new( + credentials: credentials, + dependency_files: dependency_files + ).npmrc_content + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/latest_version_finder.rb b/nub/lib/dependabot/nub/update_checker/latest_version_finder.rb new file mode 100644 index 00000000000..4c342ed64cc --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/latest_version_finder.rb @@ -0,0 +1,419 @@ +# typed: strict +# frozen_string_literal: true + +require "excon" +require "dependabot/errors" +require "dependabot/shared_helpers" +require "dependabot/package/package_latest_version_finder" +require "dependabot/nub/update_checker" +require "dependabot/update_checkers/version_filters" +require "dependabot/nub/package/registry_finder" +require "dependabot/nub/package/package_details_fetcher" +require "dependabot/nub/version" +require "dependabot/nub/requirement" +require "sorbet-runtime" + +module Dependabot + module Nub + class UpdateChecker + class PackageLatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder + extend T::Sig + + sig do + params( + dependency: Dependabot::Dependency, + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential], + ignored_versions: T::Array[String], + security_advisories: T::Array[Dependabot::SecurityAdvisory], + raise_on_ignored: T::Boolean, + cooldown_options: T.nilable(Dependabot::Package::ReleaseCooldownOptions) + ).void + end + def initialize( + dependency:, + dependency_files:, + credentials:, + ignored_versions:, + security_advisories:, + raise_on_ignored: false, + cooldown_options: nil + ) + @package_fetcher = T.let(nil, T.nilable(Package::PackageDetailsFetcher)) + super + end + + sig { returns(Package::PackageDetailsFetcher) } + def package_fetcher + return @package_fetcher if @package_fetcher + + @package_fetcher = Package::PackageDetailsFetcher.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ) + @package_fetcher + end + + sig { override.returns(T.nilable(Dependabot::Package::PackageDetails)) } + def package_details + return @package_details if @package_details + + @package_details = package_fetcher.fetch + @package_details + end + + sig do + returns(T.nilable(Dependabot::Version)) + end + def latest_version_from_registry + fetch_latest_version(language_version: nil) + end + + sig do + override.params(language_version: T.nilable(T.any(String, Dependabot::Version))) + .returns(T.nilable(Dependabot::Version)) + end + def latest_version_with_no_unlock(language_version: nil) + fetch_latest_version_with_no_unlock(language_version: language_version) + end + + sig do + params(language_version: T.nilable(T.any(String, Dependabot::Version))) + .returns(T.nilable(Dependabot::Version)) + end + def lowest_security_fix_version(language_version: nil) + fetch_lowest_security_fix_version(language_version: language_version) + end + + # This method is for latest_version_from_registry + sig do + params(language_version: T.nilable(T.any(String, Dependabot::Version))) + .returns(T.nilable(Dependabot::Version)) + end + def fetch_latest_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument + with_custom_registry_rescue do + return unless valid_npm_details? + + tag_release = version_from_dist_tags(cooldown: true) + return tag_release.version if tag_release + + return if specified_dist_tag_requirement? + + filtered_releases = filter_by_cooldown(possible_releases) + filtered_releases.find { |r| !yanked_version?(r.version) }&.version + end + end + + sig do + override + .params(language_version: T.nilable(T.any(String, Dependabot::Version))) + .returns(T.nilable(Dependabot::Version)) + end + def fetch_latest_version_with_no_unlock(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument + with_custom_registry_rescue do + return unless valid_npm_details? + return version_from_dist_tags(cooldown: true)&.version if specified_dist_tag_requirement? + + filtered_releases = filter_by_cooldown(possible_releases) + + in_range_versions = filter_out_of_range_versions(filtered_releases) + in_range_versions.find { |r| !yanked_version?(r.version) }&.version + end + end + + sig do + override + .params(language_version: T.nilable(T.any(String, Dependabot::Version))) + .returns(T.nilable(Dependabot::Version)) + end + def fetch_lowest_security_fix_version(language_version: nil) # rubocop:disable Lint/UnusedMethodArgument + with_custom_registry_rescue do + return unless valid_npm_details? + + secure_versions = + if specified_dist_tag_requirement? + [version_from_dist_tags].compact + else + possible_releases(filter_ignored: false) + end + + secure_versions = + Dependabot::UpdateCheckers::VersionFilters + .filter_vulnerable_versions( + T.unsafe(secure_versions), + security_advisories + ) + secure_versions = filter_ignored_versions(secure_versions) + secure_versions = filter_lower_versions(secure_versions) + + # Find first non-yanked version + secure_versions.sort_by(&:version).find do |version| + !yanked_version?(version.version) + end&.version + end + end + + sig do + params(releases: T::Array[Dependabot::Package::PackageRelease]) + .returns(T::Array[Dependabot::Package::PackageRelease]) + end + def filter_prerelease_versions(releases) + releases.reject do |release| + release.version.prerelease? && !related_to_current_pre?(release.version) + end + end + + sig do + override.returns(T.nilable(T::Array[Dependabot::Package::PackageRelease])) + end + def available_versions + possible_releases + end + + sig do + params(filter_ignored: T::Boolean) + .returns(T::Array[T::Array[T.untyped]]) + end + def possible_versions_with_details(filter_ignored: true) + possible_releases(filter_ignored: filter_ignored).map { |r| [r.version, r.details] } + end + + sig do + params(releases: T::Array[Dependabot::Package::PackageRelease]) + .returns(T::Array[Dependabot::Package::PackageRelease]) + end + def filter_releases(releases) + filtered = + releases + .reject do |release| + ignore_requirements.any? { |r| r.satisfied_by?(release.version) } + end + if @raise_on_ignored && + filter_lower_releases(filtered).empty? && + filter_lower_releases(releases).any? + raise Dependabot::AllVersionsIgnored + end + + if releases.count > filtered.count + Dependabot.logger.info("Filtered out #{releases.count - filtered.count} ignored versions") + end + filtered + end + + sig do + params(releases: T::Array[Dependabot::Package::PackageRelease]) + .returns(T::Array[Dependabot::Package::PackageRelease]) + end + def filter_lower_releases(releases) + return releases unless dependency.numeric_version + + releases.select { |release| release.version > dependency.numeric_version } + end + + sig do + params(filter_ignored: T::Boolean) + .returns(T::Array[Dependabot::Package::PackageRelease]) + end + def possible_releases(filter_ignored: true) + releases = possible_previous_releases.reject do |r| + r.details["deprecated"] + end + + return filter_releases(releases) if filter_ignored + + releases + end + + sig do + params(filter_ignored: T::Boolean) + .returns(T::Array[Gem::Version]) + end + def possible_versions(filter_ignored: true) + possible_releases(filter_ignored: filter_ignored).map(&:version) + end + + sig { returns(T::Array[Dependabot::Package::PackageRelease]) } + def possible_previous_releases + (package_details&.releases || []) + .reject do |r| + r.version.prerelease? && !related_to_current_pre?(T.unsafe(r.version)) + end + .sort_by(&:version).reverse + end + + sig { returns(T::Array[[Dependabot::Version, T::Hash[String, T.anything]]]) } + def possible_previous_versions_with_details + possible_previous_releases.map do |r| + [r.version, r.details] + end + end + + sig { override.returns(T::Boolean) } + def cooldown_enabled? + true + end + + private + + sig { params(_block: T.untyped).returns(T.nilable(Dependabot::Version)) } + def with_custom_registry_rescue(&_block) + yield + rescue Excon::Error::Socket, Excon::Error::Timeout, RegistryError + raise unless package_fetcher.custom_registry? + + # Custom registries can be flaky. We don't want to make that + # our problem, so quietly return `nil` here. + nil + end + + sig { returns(T::Boolean) } + def valid_npm_details? + !!package_details&.releases&.any? + end + + sig do + params(cooldown: T::Boolean) + .returns(T.nilable(Dependabot::Package::PackageRelease)) + end + def version_from_dist_tags(cooldown: false) # rubocop:disable Metrics/PerceivedComplexity + dist_tags = package_details&.dist_tags + return nil unless dist_tags + + dist_tag_req = dependency.requirements + .filter_map(&:requirement_string) + .find { |req| dist_tags.include?(req) } + + # For cooldown filtering, use filtered releases + releases = available_versions + + releases = filter_by_cooldown(releases) if cooldown && releases + + if dist_tag_req + release = find_dist_tag_release(dist_tag_req, releases) + return release unless release&.version && yanked_version?(release.version) + end + + return nil unless dist_tags["latest"] + + latest_version = Version.new(dist_tags["latest"]) + + if wants_latest_dist_tag?(latest_version) + # Find the release object for this version, even if deprecated + releases = possible_previous_releases + releases = filter_by_cooldown(releases) if cooldown + return releases.find { |r| r.version == latest_version } + end + + nil + end + + sig do + params( + dist_tag: T.nilable(String), + releases: T.nilable(T::Array[Dependabot::Package::PackageRelease]) + ) + .returns(T.nilable(Dependabot::Package::PackageRelease)) + end + def find_dist_tag_release(dist_tag, releases) + dist_tags = package_details&.dist_tags + return nil unless releases && dist_tags && dist_tag + + dist_tag_version = dist_tags[dist_tag] + + return nil unless dist_tag_version && !dist_tag_version.empty? + + release = releases.find { |r| r.version == Version.new(dist_tag_version) } + + release + end + + sig { returns(T::Boolean) } + def specified_dist_tag_requirement? + dependency.requirements.any? do |req| + requirement = req.requirement_string + next false if requirement.nil? + next false unless requirement.match?(/^[A-Za-z]/) + + !requirement.match?(/^v\d/i) + end + end + + sig do + params(version: Dependabot::Version) + .returns(T::Boolean) + end + def wants_latest_dist_tag?(version) + return false if related_to_current_pre?(version) ^ version.prerelease? + return false if current_version_greater_than?(version) + return false if current_requirement_greater_than?(version) + return false if ignore_requirements.any? { |r| r.satisfied_by?(version) } + return false if yanked_version?(version) + + true + end + + sig { params(version: Dependabot::Version).returns(T::Boolean) } + def current_requirement_greater_than?(version) + dependency.requirements.any? do |req| + requirement = req.requirement_string + next false unless requirement + + req_version = requirement.sub(/^\^|~|>=?/, "") + next false unless version_class.correct?(req_version) + + version_class.new(req_version) > version + end + end + + sig { params(version: Dependabot::Version).returns(T::Boolean) } + def related_to_current_pre?(version) + current_version = dependency.numeric_version + if current_version&.prerelease? && + current_version.release == version.release + return true + end + + dependency.requirements.any? do |req| + requirement = req.requirement_string + next unless requirement&.match?(/\d-[A-Za-z]/) + + Nub::Requirement + .requirements_array(requirement) + .any? do |r| + r.requirements.any? { |a| a.last.release == version.release } + end + rescue Gem::Requirement::BadRequirementError + false + end + end + + sig { params(version: Dependabot::Version).returns(T::Boolean) } + def current_version_greater_than?(version) + return false unless dependency.numeric_version + + T.must(dependency.numeric_version) > version + end + + sig { params(version: Dependabot::Version).returns(T::Boolean) } + def yanked_version?(version) + package_fetcher.yanked?(version) + end + + sig do + params(releases: T::Array[Dependabot::Package::PackageRelease]) + .returns(T::Array[Dependabot::Package::PackageRelease]) + end + def filter_out_of_range_versions(releases) + reqs = dependency.requirements.filter_map do |r| + Nub::Requirement.requirements_array(r.requirement_string) + end + + releases.select do |release| + reqs.all? { |r| r.any? { |o| o.satisfied_by?(release.version) } } + end + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/library_detector.rb b/nub/lib/dependabot/nub/update_checker/library_detector.rb new file mode 100644 index 00000000000..8dd5acd9753 --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/library_detector.rb @@ -0,0 +1,106 @@ +# typed: strict +# frozen_string_literal: true + +require "excon" +require "sorbet-runtime" + +require "dependabot/nub/update_checker" +require "dependabot/shared_helpers" + +module Dependabot + module Nub + class UpdateChecker + class LibraryDetector + extend T::Sig + + sig do + params( + package_json_file: Dependabot::DependencyFile, + credentials: T::Array[Dependabot::Credential], + dependency_files: T::Array[Dependabot::DependencyFile] + ) + .void + end + def initialize(package_json_file:, credentials:, dependency_files:) + @package_json_file = package_json_file + @credentials = credentials + @dependency_files = dependency_files + end + + sig { returns(T::Boolean) } + def library? + return false unless package_json_may_be_for_library? + + npm_response_matches_package_json? + end + + private + + sig { returns(Dependabot::DependencyFile) } + attr_reader :package_json_file + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Boolean) } + def package_json_may_be_for_library? + return false unless project_name + return false if T.must(project_name).match?(/\{\{.*\}\}/) + return false unless parsed_package_json["version"] + return false if parsed_package_json["private"] + + true + end + + sig { returns(T::Boolean) } + def npm_response_matches_package_json? + project_description = parsed_package_json["description"] + return false unless project_description + + # Check if the project is listed on npm. If it is, it's a library + url = "#{registry.chomp('/')}/#{escaped_project_name}" + @project_npm_response ||= T.let( + Dependabot::RegistryClient.get(url: url), + T.nilable(Excon::Response) + ) + return false unless @project_npm_response.status == 200 + + @project_npm_response.body.dup.force_encoding("UTF-8").encode + .include?(project_description) + rescue Excon::Error::Socket, Excon::Error::Timeout, URI::InvalidURIError + false + end + + sig { returns(T.nilable(String)) } + def project_name + parsed_package_json.fetch("name", nil) + end + + sig { returns(T.nilable(String)) } + def escaped_project_name + project_name&.gsub("/", "%2F") + end + + sig { returns(T::Hash[String, T.untyped]) } + def parsed_package_json + @parsed_package_json ||= T.let( + JSON.parse(T.must(package_json_file.content)), + T.nilable(T::Hash[String, T.untyped]) + ) + end + + sig { returns(String) } + def registry + Nub::Package::RegistryFinder.new( + dependency: nil, + credentials: credentials, + npmrc_file: dependency_files.find { |f| f.name.end_with?(".npmrc") } + ).registry_from_rc(T.must(project_name)) || "https://registry.npmjs.org" + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/requirements_updater.rb b/nub/lib/dependabot/nub/update_checker/requirements_updater.rb new file mode 100644 index 00000000000..be74efad02f --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/requirements_updater.rb @@ -0,0 +1,252 @@ +# typed: strict +# frozen_string_literal: true + +################################################################################ +# For more details on npm version constraints, see: # +# https://docs.npmjs.com/misc/semver # +################################################################################ + +require "sorbet-runtime" + +require "dependabot/nub/requirement" +require "dependabot/nub/update_checker" +require "dependabot/nub/version" +require "dependabot/dependency_requirement" +require "dependabot/requirements_update_strategy" + +module Dependabot + module Nub + class UpdateChecker + class RequirementsUpdater + extend T::Sig + + VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/ + SEPARATOR = /(?<=[a-zA-Z0-9*])[\s|]+(?![\s|-])/ + ALLOWED_UPDATE_STRATEGIES = T.let( + [ + RequirementsUpdateStrategy::LockfileOnly, + RequirementsUpdateStrategy::WidenRanges, + RequirementsUpdateStrategy::BumpVersions, + RequirementsUpdateStrategy::BumpVersionsIfNecessary + ].freeze, + T::Array[Dependabot::RequirementsUpdateStrategy] + ) + + sig do + params( + requirements: T::Array[Dependabot::DependencyRequirement], + updated_source: T.nilable(Dependabot::DependencyRequirement::ObjectHash), + update_strategy: Dependabot::RequirementsUpdateStrategy, + latest_resolvable_version: T.nilable(T.any(String, Gem::Version)) + ) + .void + end + def initialize( + requirements:, + updated_source:, + update_strategy:, + latest_resolvable_version: + ) + @requirements = T.let( + requirements.map { |req| Dependabot::DependencyRequirement.create(req) }, + T::Array[Dependabot::DependencyRequirement] + ) + @updated_source = updated_source + @update_strategy = update_strategy + + check_update_strategy + + return unless latest_resolvable_version + + @latest_resolvable_version = T.let( + version_class.new(latest_resolvable_version), + Nub::Version + ) + end + + sig { returns(T::Array[Dependabot::DependencyRequirement]) } + def updated_requirements + return requirements if update_strategy.lockfile_only? + + requirements.map do |req| + req = Dependabot::DependencyRequirement.create(req.merge(source: updated_source)) + next req unless latest_resolvable_version + next initial_req_after_source_change(req) unless req.requirement_string + next req if T.must(req.requirement_string).match?(/^([A-Za-uw-z]|v[^\d])/) + + case update_strategy + when RequirementsUpdateStrategy::WidenRanges then widen_requirement(req) + when RequirementsUpdateStrategy::BumpVersions then update_version_requirement(req) + when RequirementsUpdateStrategy::BumpVersionsIfNecessary + update_version_requirement_if_needed(req) + else raise "Unexpected update strategy: #{update_strategy}" + end + end + end + + private + + sig { returns(T::Array[Dependabot::DependencyRequirement]) } + attr_reader :requirements + + sig { returns(T.nilable(Dependabot::DependencyRequirement::ObjectHash)) } + attr_reader :updated_source + + sig { returns(Dependabot::RequirementsUpdateStrategy) } + attr_reader :update_strategy + + sig { returns(T.nilable(Nub::Version)) } + attr_reader :latest_resolvable_version + + sig { void } + def check_update_strategy + return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy) + + raise "Unknown update strategy: #{update_strategy}" + end + + sig { returns(T::Boolean) } + def updating_from_git_to_npm? + return false unless updated_source.nil? + + original_source = requirements.find(&:source) + original_source&.source_string("type") == "git" + end + + sig { params(req: Dependabot::DependencyRequirement).returns(Dependabot::DependencyRequirement) } + def initial_req_after_source_change(req) + return req unless updating_from_git_to_npm? + return req unless req.requirement_string.nil? + + Dependabot::DependencyRequirement.create(req.merge(requirement: "^#{latest_resolvable_version}")) + end + + sig { params(req: Dependabot::DependencyRequirement).returns(Dependabot::DependencyRequirement) } + def update_version_requirement(req) + current_requirement = T.must(req.requirement_string) + + if current_requirement.match?(/(<|-\s)/i) + ruby_req = ruby_requirements(current_requirement).first + return req if ruby_req&.satisfied_by?(latest_resolvable_version) + + updated_req = update_range_requirement(current_requirement) + return Dependabot::DependencyRequirement.create(req.merge(requirement: updated_req)) + end + + reqs = current_requirement.strip.split(SEPARATOR).map(&:strip) + Dependabot::DependencyRequirement.create(req.merge(requirement: update_version_string(T.must(reqs.first)))) + end + + sig { params(req: Dependabot::DependencyRequirement).returns(Dependabot::DependencyRequirement) } + def update_version_requirement_if_needed(req) + current_requirement = T.must(req.requirement_string) + version = latest_resolvable_version + return req if current_requirement.strip == "" + + ruby_reqs = ruby_requirements(current_requirement) + return req if ruby_reqs.any? { |r| r.satisfied_by?(version) } + + update_version_requirement(req) + end + + sig { params(req: Dependabot::DependencyRequirement).returns(Dependabot::DependencyRequirement) } + def widen_requirement(req) + current_requirement = T.must(req.requirement_string) + version = latest_resolvable_version + return req if current_requirement.strip == "" + + ruby_reqs = ruby_requirements(current_requirement) + return req if ruby_reqs.any? { |r| r.satisfied_by?(version) } + + reqs = current_requirement.strip.split(SEPARATOR).map(&:strip) + + updated_requirement = + if reqs.any? { |r| r.match?(/(<|-\s)/i) } + update_range_requirement(current_requirement) + elsif current_requirement.strip.split(SEPARATOR).one? + update_version_string(current_requirement) + else + current_requirement + end + + Dependabot::DependencyRequirement.create(req.merge(requirement: updated_requirement)) + end + + sig { params(requirement_string: String).returns(T::Array[Nub::Requirement]) } + def ruby_requirements(requirement_string) + Nub::Requirement + .requirements_array(requirement_string) + end + + sig { params(req_string: String).returns(String) } + def update_range_requirement(req_string) + range_requirements = + req_string.split(SEPARATOR).select { |r| r.match?(/<|(\s+-\s+)/) } + + if range_requirements.one? + range_requirement = T.must(range_requirements.first) + versions = range_requirement.scan(VERSION_REGEX) + version_objects = versions.map { |v| version_class.new(v.to_s) } + upper_bound = T.must(version_objects.max) + new_upper_bound = update_greatest_version( + upper_bound.to_s, + T.must(latest_resolvable_version) + ) + + req_string.sub( + upper_bound.to_s, + new_upper_bound.to_s + ) + else + req_string + " || ^#{latest_resolvable_version}" + end + end + + sig { params(req_string: String).returns(String) } + def update_version_string(req_string) + req_string + .sub(VERSION_REGEX) do |old_version| + if old_version.match?(/\d-/) || + T.must(latest_resolvable_version).to_s.match?(/\d-/) + T.must(latest_resolvable_version).to_s + else + old_parts = old_version.split(".") + new_parts = T.must(latest_resolvable_version).to_s.split(".") + .first(old_parts.count) + new_parts.map.with_index do |part, i| + old_parts[i]&.match?(/^x\b/) ? "x" : part + end.join(".") + end + end + end + + sig { params(old_version: String, version_to_be_permitted: Nub::Version).returns(String) } + def update_greatest_version(old_version, version_to_be_permitted) + version = version_class.new(old_version) + version = version.release if version.prerelease? + + index_to_update = + version.segments.map.with_index { |seg, i| T.cast(seg, Integer).zero? ? 0 : i }.max || 0 + + version.segments.map.with_index do |_, index| + segment_value = + if index < index_to_update + T.cast(version_to_be_permitted.segments[index], Integer) + elsif index == index_to_update + # Cast to Integer before adding 1 to ensure correct type + T.cast(version_to_be_permitted.segments[index], Integer) + 1 + else + 0 + end + segment_value.to_s + end.join(".") + end + + sig { returns(T.class_of(Nub::Version)) } + def version_class + Nub::Version + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/subdependency_version_resolver.rb b/nub/lib/dependabot/nub/update_checker/subdependency_version_resolver.rb new file mode 100644 index 00000000000..fc4f7cc620e --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/subdependency_version_resolver.rb @@ -0,0 +1,202 @@ +# typed: strong +# frozen_string_literal: true + +require "sorbet-runtime" + +require "dependabot/dependency" +require "dependabot/errors" +require "dependabot/logger" +require "dependabot/nub/file_parser" +require "dependabot/nub/helpers" +require "dependabot/nub/native_helpers" +require "dependabot/nub/sub_dependency_files_filterer" +require "dependabot/nub/update_checker" +require "dependabot/nub/update_checker/dependency_files_builder" +require "dependabot/nub/version" +require "dependabot/shared_helpers" + +module Dependabot + module Nub + class UpdateChecker + class SubdependencyVersionResolver + extend T::Sig + + sig { returns(Dependency) } + attr_reader :dependency + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[String]) } + attr_reader :ignored_versions + + sig { returns(T.nilable(T.any(String, Gem::Version))) } + attr_reader :latest_allowable_version + + sig { returns(T.nilable(String)) } + attr_reader :repo_contents_path + + sig do + params( + dependency: Dependency, + credentials: T::Array[Dependabot::Credential], + dependency_files: T::Array[Dependabot::DependencyFile], + ignored_versions: T::Array[String], + latest_allowable_version: T.nilable(T.any(String, Gem::Version)), + repo_contents_path: T.nilable(String) + ).void + end + def initialize( + dependency:, + credentials:, + dependency_files:, + ignored_versions:, + latest_allowable_version:, + repo_contents_path: + ) + @dependency = dependency + @credentials = credentials + @dependency_files = dependency_files + @ignored_versions = ignored_versions + @latest_allowable_version = latest_allowable_version + @repo_contents_path = repo_contents_path + end + + sig { returns(T.nilable(T.any(String, Gem::Version))) } + def latest_resolvable_version + raise "Not a subdependency!" if dependency.requirements.any? + return if bundled_dependency? + + base_dir = T.must(dependency_files.first).directory + SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do + dependency_files_builder.write_temporary_dependency_files + + updated_lockfiles = filtered_lockfiles.map do |lockfile| + updated_content = update_subdependency_in_lockfile(lockfile) + updated_lockfile = lockfile.dup + updated_lockfile.content = updated_content + updated_lockfile + end + + version_from_updated_lockfiles(updated_lockfiles) + end + rescue SharedHelpers::HelperSubprocessFailed + # TODO: Move error handling logic from the FileUpdater to this class + + # Return nil (no update possible) if an unknown error occurred + nil + end + + private + + sig { params(lockfile: Dependabot::DependencyFile).returns(String) } + def update_subdependency_in_lockfile(lockfile) + lockfile_name = Pathname.new(lockfile.name).basename.to_s + path = Pathname.new(lockfile.name).dirname.to_s + + updated_files = if lockfile.name.end_with?("nub.lock") + run_nub_updater(path, lockfile_name) + else + raise "Unsupported lockfile type: #{lockfile.name}" + end + + updated_files.fetch(lockfile_name) + end + + sig { params(updated_lockfiles: T::Array[Dependabot::DependencyFile]).returns(T.nilable(Gem::Version)) } + def version_from_updated_lockfiles(updated_lockfiles) + updated_files = dependency_files - + dependency_files_builder.lockfiles + + updated_lockfiles + + updated_version = Nub::FileParser.new( + dependency_files: updated_files, + source: nil, + credentials: credentials + ).parse.find { |d| d.name == dependency.name }&.version + return unless updated_version + + version_class.new(updated_version) + end + + sig { params(path: String, lockfile_name: String).returns(T::Hash[String, String]) } + def run_nub_updater(path, lockfile_name) + SharedHelpers.with_git_configured(credentials: credentials) do + Dir.chdir(path) do + Helpers.run_nub_command( + "update #{dependency.name} --lockfile-only --ignore-scripts", + fingerprint: "update --lockfile-only --ignore-scripts" + ) + { lockfile_name => File.read(lockfile_name) } + end + end + end + + sig { returns(T.class_of(Dependabot::Version)) } + def version_class + dependency.version_class + end + + sig { returns(Dependabot::Dependency) } + def updated_dependency + Dependabot::Dependency.new( + name: dependency.name, + version: T.cast(latest_allowable_version, T.nilable(T.any(String, Dependabot::Version))), + previous_version: dependency.version, + requirements: [], + package_manager: dependency.package_manager + ) + end + + sig { returns(T::Array[Dependabot::DependencyFile]) } + def filtered_lockfiles + @filtered_lockfiles ||= T.let( + SubDependencyFilesFilterer.new( + dependency_files: dependency_files, + updated_dependencies: [updated_dependency] + ).files_requiring_update, + T.nilable(T::Array[Dependabot::DependencyFile]) + ) + end + + sig { returns(Dependabot::Nub::UpdateChecker::DependencyFilesBuilder) } + def dependency_files_builder + @dependency_files_builder ||= T.let( + DependencyFilesBuilder.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ), + T.nilable(Dependabot::Nub::UpdateChecker::DependencyFilesBuilder) + ) + end + + # TODO: We should try and fix this by updating the parent that's not + # bundled. For this case: `chokidar > fsevents > node-pre-gyp > tar` we + # would need to update `fsevents` + # + # We shouldn't update bundled sub-dependencies as they have been bundled + # into the release at an exact version by a parent using + # `bundledDependencies`. + # + # For example, fsevents < 2 bundles node-pre-gyp meaning all it's + # sub-dependencies get bundled into the release tarball at publish time + # so you always get the same sub-dependency versions if you re-install a + # specific version of fsevents. + # + # Updating the sub-dependency by deleting the entry works but it gets + # removed from the bundled set of dependencies and moved top level + # resulting in a bunch of package duplication which is pretty confusing. + sig { returns(T::Boolean) } + def bundled_dependency? + dependency.subdependency_metadata + &.any? { |h| h.fetch(:npm_bundled, false) } || + false + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/version_resolver.rb b/nub/lib/dependabot/nub/update_checker/version_resolver.rb new file mode 100644 index 00000000000..c0aaa590787 --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/version_resolver.rb @@ -0,0 +1,778 @@ +# typed: strict +# frozen_string_literal: true + +require "json" +require "sorbet-runtime" + +require "dependabot/errors" +require "dependabot/git_commit_checker" +require "dependabot/logger" +require "dependabot/nub/dependency_files_filterer" +require "dependabot/nub/file_parser" +require "dependabot/nub/file_updater/npmrc_builder" +require "dependabot/nub/file_updater/package_json_preparer" +require "dependabot/nub/helpers" +require "dependabot/nub/native_helpers" +require "dependabot/nub/package_name" +require "dependabot/nub/requirement" +require "dependabot/nub/update_checker" +require "dependabot/nub/version" +require "dependabot/shared_helpers" + +# rubocop:disable-next Metrics/ClassLength +module Dependabot + module Nub + class UpdateChecker + class VersionResolver + extend T::Sig + + require_relative "latest_version_finder" + + TIGHTLY_COUPLED_MONOREPOS = T.let( + { + "vue" => %w(vue vue-template-compiler) + }.freeze, + T::Hash[String, T::Array[String]] + ) + + # Manifest groups the candidate version is pinned into before re-resolving; includes + # peerDependencies (unlike FileParser::DEPENDENCY_TYPES) so a peer-only dep is pinned too. + PINNABLE_DEPENDENCY_GROUPS = %w(dependencies devDependencies optionalDependencies peerDependencies).freeze + + # Error message returned by `npm install` (for NPM 6): + # react-dom@15.2.0 requires a peer of react@^15.2.0 \ + # but none is installed. You must install peer dependencies yourself. + NPM6_PEER_DEP_ERROR_REGEX = + / + (?[^\s]+)\s + requires\sa\speer\sof\s + (?.+?)\sbut\snone\sis\sinstalled. + /x + + # Error message returned by `npm install` (for NPM 8): + # npm ERR! Could not resolve dependency: + # npm ERR! peer react@"^16.14.0" from react-dom@16.14.0 + # + # or with two semver constraints: + # npm ERR! Could not resolve dependency: + # npm ERR! peer @opentelemetry/api@">=1.0.0 <1.1.0" from @opentelemetry/context-async-hooks@1.0.1 + NPM8_PEER_DEP_ERROR_REGEX = + / + npm\s(?:WARN|ERR!)\sCould\snot\sresolve\sdependency:\n + npm\s(?:WARN|ERR!)\speer\s(?\S+@\S+(\s\S+)?)\sfrom\s(?\S+@\S+) + /x + + sig do + params( + dependency: Dependabot::Dependency, + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential], + latest_allowable_version: T.nilable(T.any(String, Gem::Version)), + latest_version_finder: PackageLatestVersionFinder, + repo_contents_path: T.nilable(String), + dependency_group: T.nilable(Dependabot::DependencyGroup), + raise_on_ignored: T::Boolean, + update_cooldown: T.nilable(Dependabot::Package::ReleaseCooldownOptions) + ).void + end + def initialize( # rubocop:disable Metrics/AbcSize + dependency:, + dependency_files:, + credentials:, + latest_allowable_version:, + latest_version_finder:, + repo_contents_path:, + dependency_group: nil, + raise_on_ignored: false, + update_cooldown: nil + ) + @dependency = dependency + @dependency_files = dependency_files + @credentials = credentials + @latest_allowable_version = latest_allowable_version + @dependency_group = dependency_group + + @latest_version_finder = T.let({}, T::Hash[Dependabot::Dependency, PackageLatestVersionFinder]) + @latest_version_finder[dependency] = latest_version_finder + @repo_contents_path = repo_contents_path + @raise_on_ignored = raise_on_ignored + @update_cooldown = update_cooldown + + @types_package = T.let(nil, T.nilable(Dependabot::Dependency)) + @original_package = T.let(nil, T.nilable(Dependabot::Dependency)) + @latest_types_package_version = T.let(nil, T.nilable(Dependabot::Version)) + @dependency_files_builder = T.let(nil, T.nilable(DependencyFilesBuilder)) + @resolve_latest_previous_version = T.let({}, T::Hash[Dependabot::Dependency, T.nilable(String)]) + @paths_requiring_update_check = T.let(nil, T.nilable(T::Array[String])) + @top_level_dependencies = T.let(nil, T.nilable(T::Array[Dependabot::Dependency])) + @old_peer_dependency_errors = T.let( + nil, T.nilable(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) + ) + @peer_dependency_errors = T.let(nil, T.nilable(T::Array[T.any(T::Hash[String, T.nilable(String)], String)])) + end + + sig { returns(T.nilable(T.any(String, Gem::Version))) } + def latest_resolvable_version + return latest_allowable_version if git_dependency?(dependency) + return if part_of_tightly_locked_monorepo? + return if types_update_available? + return if original_package_update_available? + + return latest_allowable_version unless relevant_unmet_peer_dependencies.any? + + satisfying_versions.first + end + + sig { returns(T::Boolean) } + def latest_version_resolvable_with_full_unlock? + return false if dependency_updates_from_full_unlock.nil? + + true + end + + sig do + params( + updated_version: T.nilable(T.any(String, Gem::Version)) + ).returns(T.nilable(T.any(String, Gem::Version))) + end + def latest_resolvable_previous_version(updated_version) + resolve_latest_previous_version(dependency, updated_version) + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { returns(T.nilable(T::Array[T::Hash[String, T.nilable(String)]])) } + def dependency_updates_from_full_unlock + return if git_dependency?(dependency) + return updated_monorepo_dependencies if part_of_tightly_locked_monorepo? + return if newly_broken_peer_reqs_from_dep.any? + return if original_package_update_available? + + updates = [{ + dependency: dependency, + version: latest_allowable_version, + previous_version: latest_resolvable_previous_version( + latest_allowable_version + ) + }] + newly_broken_peer_reqs_on_dep.each do |peer_req| + dep_name = peer_req.fetch(:requiring_dep_name) + dep = top_level_dependencies.find { |d| d.name == dep_name } + + # Can't handle reqs from sub-deps or git source deps (yet) + return nil if dep.nil? + return nil if git_dependency?(dep) + + updated_version = + latest_version_of_dep_with_satisfied_peer_reqs(dep) + return nil unless updated_version + + updates << { + dependency: dep, + version: updated_version, + previous_version: resolve_latest_previous_version( + dep, updated_version + ) + } + end + updates += updated_types_dependencies if types_update_available? + updates.uniq + end + # rubocop:enable Metrics/PerceivedComplexity + + private + + sig { returns(Dependabot::Dependency) } + attr_reader :dependency + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { returns(T.nilable(T.any(String, Gem::Version))) } + attr_reader :latest_allowable_version + + sig { returns(T.nilable(String)) } + attr_reader :repo_contents_path + + sig { returns(T.nilable(Dependabot::DependencyGroup)) } + attr_reader :dependency_group + + sig { returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) } + attr_reader :update_cooldown + + sig { returns(T::Boolean) } + attr_reader :raise_on_ignored + + sig { params(dep: Dependabot::Dependency).returns(PackageLatestVersionFinder) } + def latest_version_finder(dep) + @latest_version_finder[dep] ||= + PackageLatestVersionFinder.new( + dependency: dep, + dependency_files: dependency_files, + credentials: credentials, + cooldown_options: update_cooldown, + ignored_versions: [], + security_advisories: [], + raise_on_ignored: raise_on_ignored + ) + end + + # rubocop:disable Metrics/PerceivedComplexity + sig do + params( + dep: Dependabot::Dependency, + updated_version: T.nilable(T.any(String, Gem::Version)) + ).returns(T.nilable(String)) + end + def resolve_latest_previous_version(dep, updated_version) + return dep.version if dep.version + + @resolve_latest_previous_version[dep] ||= begin + relevant_versions = latest_version_finder(dependency) + .possible_previous_versions_with_details + .map(&:first) + reqs = dep.requirements.filter_map(&:requirement_string) + .map { |r| requirement_class.requirements_array(r) } + + # Pick the lowest version from the max possible version from all + # requirements. This matches the logic when combining the same + # dependency in DependencySet from multiple manifest files where we + # pick the lowest version from the duplicates. + latest_previous_version = reqs.flat_map do |req| + relevant_versions.select do |version| + req.any? { |r| r.satisfied_by?(version) } + end.max + end.min&.to_s + + # Handle cases where the latest resolvable previous version is the + # latest version. This often happens if you don't have lockfiles and + # have requirements update strategy set to bump_versions, where an + # update might go from ^1.1.1 to ^1.1.2 (both resolve to 1.1.2). + if updated_version.to_s == latest_previous_version + nil + else + latest_previous_version + end + end + end + # rubocop:enable Metrics/PerceivedComplexity + + sig { returns(T::Boolean) } + def part_of_tightly_locked_monorepo? + monorepo_dep_names = + TIGHTLY_COUPLED_MONOREPOS.values + .find { |deps| deps.include?(dependency.name) } + return false unless monorepo_dep_names + + deps_to_update = + top_level_dependencies + .select { |d| monorepo_dep_names.include?(d.name) } + + deps_to_update.count > 1 + end + + sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def updated_monorepo_dependencies + monorepo_dep_names = + TIGHTLY_COUPLED_MONOREPOS.values + .find { |deps| deps.include?(dependency.name) } + + deps_to_update = + top_level_dependencies + .select { |d| monorepo_dep_names&.include?(d.name) } + + updates = [] + deps_to_update.each do |dep| + next if git_dependency?(dep) + next if dep.version && + version_class.new(dep.version) >= latest_allowable_version + + updated_version = + latest_version_finder(dep) + .possible_versions + .find { |v| v == latest_allowable_version } + next unless updated_version + + updates << { + dependency: dep, + version: updated_version, + previous_version: resolve_latest_previous_version( + dep, updated_version + ) + } + end + + updates + end + + sig { returns(T.nilable(Dependabot::Dependency)) } + def types_package + return @types_package if @types_package + + @types_package = begin + types_package_name = PackageName.new(dependency.name).types_package_name + top_level_dependencies.find { |d| types_package_name.to_s == d.name } if types_package_name + end + @types_package + end + + sig { returns(T.nilable(Dependabot::Dependency)) } + def original_package + return @original_package if @original_package + + @original_package = begin + original_package_name = PackageName.new(dependency.name).library_name + top_level_dependencies.find { |d| original_package_name.to_s == d.name } if original_package_name + end + @original_package + end + + sig { returns(T.nilable(Dependabot::Version)) } + def latest_types_package_version + types_pkg = types_package + return unless types_pkg + + return @latest_types_package_version if @latest_types_package_version + + @latest_types_package_version = latest_version_finder(types_pkg).latest_version_from_registry + @latest_types_package_version + end + + sig { returns(T::Boolean) } + def types_update_available? + types_pkg = types_package + return false unless types_pkg + + latest_types_version = latest_types_package_version + return false unless latest_types_version + + latest_allowable_ver = latest_allowable_version + return false unless latest_allowable_ver.is_a?(Version) && latest_allowable_ver.backwards_compatible_with?( + T.unsafe(latest_types_version) + ) + + return false unless version_class.correct?(types_pkg.version) + + current_types_package_version = version_class.new(types_pkg.version) + + return false unless current_types_package_version < latest_types_version + + true + end + + sig { returns(T::Boolean) } + def original_package_update_available? + original_pack = original_package + return false unless original_pack + + return false unless version_class.correct?(original_pack.version) + + original_package_version = version_class.new(original_pack.version) + + latest_version = latest_version_finder(original_pack).latest_version_from_registry + + # If the latest version is within the scope of the current requirements, + # latest_version will be nil. In such cases, there is no update available. + return false if latest_version.nil? + + original_package_version < latest_version + end + + sig { returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def updated_types_dependencies + [{ + dependency: types_package, + version: latest_types_package_version, + previous_version: resolve_latest_previous_version( + T.must(types_package), T.cast(latest_types_package_version, Gem::Version) + ) + }] + end + + sig { returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) } + def peer_dependency_errors + return @peer_dependency_errors if @peer_dependency_errors + + @peer_dependency_errors = fetch_peer_dependency_errors(version: latest_allowable_version) + @peer_dependency_errors + end + + sig { returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) } + def old_peer_dependency_errors + return @old_peer_dependency_errors if @old_peer_dependency_errors + + version = version_for_dependency(dependency) + + @old_peer_dependency_errors = fetch_peer_dependency_errors(version: version) + @old_peer_dependency_errors + end + + sig do + params( + version: T.nilable(T.any(String, Gem::Version)) + ).returns(T::Array[T.any(T::Hash[String, T.nilable(String)], String)]) + end + def fetch_peer_dependency_errors(version:) + # TODO: Add all of the error handling that the FileUpdater does + # here (since problematic repos will be resolved here before they're + # seen by the FileUpdater) + base_dir = T.must(dependency_files.first).directory + SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do + dependency_files_builder.write_temporary_dependency_files + + paths_requiring_update_check.flat_map do |path| + run_checker(path: path, version: version) + end.compact + end + rescue SharedHelpers::HelperSubprocessFailed + # Fall back to allowing the version through. Whatever error + # occurred should be properly handled by the FileUpdater. We + # can slowly migrate error handling to this class over time. + [] + end + + sig { params(message: String).returns(T::Array[T::Hash[String, T.nilable(String)]]) } + def handle_peer_dependency_errors(message) + errors = [] + if message.match?(NPM6_PEER_DEP_ERROR_REGEX) + message.scan(NPM6_PEER_DEP_ERROR_REGEX) do + errors << Regexp.last_match&.named_captures + end + elsif message.match?(NPM8_PEER_DEP_ERROR_REGEX) + message.scan(NPM8_PEER_DEP_ERROR_REGEX) do + errors << T.must(Regexp.last_match).named_captures + end + else + raise + end + errors + end + + sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) } + def unmet_peer_dependencies + peer_dependency_errors + .map { |captures| error_details_from_captures(captures) } + end + + sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) } + def old_unmet_peer_dependencies + old_peer_dependency_errors + .map { |captures| error_details_from_captures(captures) } + end + + sig do + params(captures: T.any(T::Hash[String, T.nilable(String)], String)) + .returns(T::Hash[Symbol, T.nilable(String)]) + end + def error_details_from_captures(captures) + return {} unless captures.is_a?(Hash) + + required_dep_captures = captures.fetch("required_dep") + requiring_dep_captures = captures.fetch("requiring_dep") + return {} unless required_dep_captures && requiring_dep_captures + + { + requirement_name: required_dep_captures.sub(/@[^@]+$/, ""), + requirement_version: required_dep_captures.split("@").last&.delete('"'), + requiring_dep_name: requiring_dep_captures.sub(/@[^@]+$/, "") + } + end + + sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) } + def relevant_unmet_peer_dependencies # rubocop:disable Metrics/PerceivedComplexity + relevant_unmet_peer_dependencies = + unmet_peer_dependencies.select do |dep| + dep[:requirement_name] == dependency.name || + dep[:requiring_dep_name] == dependency.name + end + + unless dependency_group.nil? + # Ignore unmet peer dependencies that are in the dependency group because + # the update is also updating those dependencies. + relevant_unmet_peer_dependencies.reject! do |dep| + dependency_group&.dependencies&.any? do |group_dep| + dep[:requirement_name] == group_dep.name || + dep[:requiring_dep_name] == group_dep.name + end + end + end + + return [] if relevant_unmet_peer_dependencies.empty? + + # Prune out any pre-existing warnings + relevant_unmet_peer_dependencies.reject do |issue| + old_unmet_peer_dependencies.any? do |old_issue| + old_issue.slice(:requirement_name, :requiring_dep_name) == + issue.slice(:requirement_name, :requiring_dep_name) + end + end + end + + # rubocop:disable Metrics/PerceivedComplexity + sig { returns(T::Array[T.any(String, Gem::Version)]) } + def satisfying_versions + latest_version_finder(dependency) + .possible_versions_with_details + .select do |versions_with_details| + version, details = versions_with_details + next false unless satisfies_peer_reqs_on_dep?(T.unsafe(version)) + next true unless details["peerDependencies"] + next true if version == version_for_dependency(dependency) + + details["peerDependencies"].all? do |dep, req| + dep = top_level_dependencies.find { |d| d.name == dep } + next false unless dep + next git_dependency?(dep) if req.include?("/") + + reqs = requirement_class.requirements_array(req) + next false unless version_for_dependency(dep) + + reqs.any? { |r| r.satisfied_by?(version_for_dependency(dep)) } + rescue Gem::Requirement::BadRequirementError + false + end + end.map do |versions_with_details| # rubocop:disable Style/MultilineBlockChain + # Return just the version + version, = versions_with_details + version + end + end + + # rubocop:enable Metrics/PerceivedComplexity + + sig { params(version: T.nilable(T.any(String, Gem::Version))).returns(T::Boolean) } + def satisfies_peer_reqs_on_dep?(version) + newly_broken_peer_reqs_on_dep.all? do |peer_req| + req = peer_req.fetch(:requirement_version) + + # Git requirements can't be satisfied by a version + next false if req&.include?("/") + + reqs = requirement_class.requirements_array(req) + reqs.any? { |r| r.satisfied_by?(version) } + rescue Gem::Requirement::BadRequirementError + false + end + end + + sig { params(dep: Dependabot::Dependency).returns(T.nilable(T.any(String, Gem::Version))) } + def latest_version_of_dep_with_satisfied_peer_reqs(dep) # rubocop:disable Metrics/PerceivedComplexity + dependency_version = version_for_dependency(dep) + version_with_detail = + latest_version_finder(dep) + .possible_versions_with_details + .find do |version_details| + version, details = version_details + + next false unless !dependency_version || version > dependency_version + next true unless details["peerDependencies"] + + details["peerDependencies"].all? do |peer_dep_name, req| + # Can't handle multiple peer dependencies + next false unless peer_dep_name == dependency.name + next git_dependency?(dependency) if req.include?("/") + + reqs = requirement_class.requirements_array(req) + + reqs.any? { |r| r.satisfied_by?(latest_allowable_version) } + rescue Gem::Requirement::BadRequirementError + false + end + end + version_with_detail.is_a?(Array) ? version_with_detail.first : version_with_detail + end + + sig { params(dep: Dependabot::Dependency).returns(T::Boolean) } + def git_dependency?(dep) + # ignored_version/raise_on_ignored are irrelevant. + GitCommitChecker + .new(dependency: dep, credentials: credentials) + .git_dependency? + end + + sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) } + def newly_broken_peer_reqs_on_dep + relevant_unmet_peer_dependencies + .select { |dep| dep[:requirement_name] == dependency.name } + end + + sig { returns(T::Array[T::Hash[Symbol, T.nilable(String)]]) } + def newly_broken_peer_reqs_from_dep + relevant_unmet_peer_dependencies + .select { |dep| dep[:requiring_dep_name] == dependency.name } + end + + sig do + params( + lockfiles: T::Array[Dependabot::DependencyFile], + path: String + ).returns(T::Array[Dependabot::DependencyFile]) + end + def lockfiles_for_path(lockfiles:, path:) + lockfiles.select do |lockfile| + File.dirname(lockfile.name) == File.dirname(path) + end + end + + sig do + params( + path: String, + version: T.nilable(T.any(String, Gem::Version)) + ).returns(T.nilable(T.any(T::Hash[String, T.untyped], String, T::Array[T::Hash[String, T.untyped]]))) + end + def run_checker(path:, version:) + nub_lockfiles = lockfiles_for_path(lockfiles: dependency_files_builder.nub_locks, path: path) + return run_nub_checker(path: path, version: version) if nub_lockfiles.any? + + root_nub_lock = dependency_files_builder.root_nub_lock + run_nub_checker(path: path, version: version) if root_nub_lock + rescue SharedHelpers::HelperSubprocessFailed => e + handle_peer_dependency_errors(e.message) + end + + sig do + params( + path: String, + version: T.nilable(T.any(String, Gem::Version)) + ).returns(T.untyped) + end + def run_nub_checker(path:, version:) + # nub is pnpm-compatible and rejects `update @`, so pin the candidate + # version into the manifests and re-resolve lockfile-only — a peer-dependency conflict then + # surfaces as a subprocess failure the caller classifies (same pin approach the FileUpdater + # uses; nub has no `install @` / `update @` add-a-specific-version form). + SharedHelpers.with_git_configured(credentials: credentials) do + Dir.chdir(path) do + pin_dependency_version_in_manifests(version) + Helpers.run_nub_command( + "install --lockfile-only --ignore-scripts", + fingerprint: "install --lockfile-only --ignore-scripts" + ) + end + end + end + + sig { params(version: T.nilable(T.any(String, Gem::Version))).void } + def pin_dependency_version_in_manifests(version) + return unless version + + Dir.glob("**/package.json").each do |manifest| + parsed = JSON.parse(File.read(manifest)) + changed = T.let(false, T::Boolean) + + PINNABLE_DEPENDENCY_GROUPS.each do |group| + group_deps = parsed[group] + next unless group_deps.is_a?(Hash) && group_deps.key?(dependency.name) + + group_deps[dependency.name] = version.to_s + changed = true + end + + File.write(manifest, JSON.pretty_generate(parsed)) if changed + end + end + + sig do + params( + version: T.nilable(T.any(String, Gem::Version)) + ).returns(String) + end + def version_install_arg(version:) + git_source = dependency.requirements.find { |req| req.source_string("type") == "git" } + + if git_source + "#{dependency.name}@#{git_source.source_string('url')}##{version}" + else + "#{dependency.name}@#{version}" + end + end + + sig do + params( + requirements: T::Array[T::Hash[Symbol, T.untyped]], + path: String + ).returns(T::Array[T::Hash[Symbol, T.untyped]]) + end + def requirements_for_path(requirements, path) + return requirements if path.to_s == "." + + requirements.filter_map do |r| + next unless r[:file].start_with?("#{path}/") + + r.merge(file: r[:file].gsub(/^#{Regexp.quote("#{path}/")}/, "")) + end + end + + # Top level dependencies are required in the peer dep checker + # to fetch the manifests for all top level deps which may contain + # "peerDependency" requirements + sig { returns(T::Array[Dependabot::Dependency]) } + def top_level_dependencies + return @top_level_dependencies if @top_level_dependencies + + @top_level_dependencies = Nub::FileParser.new( + dependency_files: dependency_files, + source: nil, + credentials: credentials + ).parse.select(&:top_level?) + @top_level_dependencies + end + + sig { returns(T::Array[String]) } + def paths_requiring_update_check + return @paths_requiring_update_check if @paths_requiring_update_check + + @paths_requiring_update_check = + DependencyFilesFilterer.new( + dependency_files: dependency_files, + updated_dependencies: [dependency] + ).paths_requiring_update_check + @paths_requiring_update_check + end + + sig { returns(DependencyFilesBuilder) } + def dependency_files_builder + return @dependency_files_builder if @dependency_files_builder + + @dependency_files_builder = + DependencyFilesBuilder.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ) + @dependency_files_builder + end + + sig { params(dep: Dependabot::Dependency).returns(T.nilable(T.any(String, Gem::Version))) } + def version_for_dependency(dep) + return version_class.new(dep.version) if dep.version && version_class.correct?(dep.version) + + dep.requirements.filter_map(&:requirement_string) + .reject { |req_string| req_string.start_with?("<") } + .select { |req_string| req_string.match?(version_regex) } + .map { |req_string| req_string.match(version_regex) } + .select { |version| version_class.correct?(version.to_s) } + .map { |version| version_class.new(version.to_s) } + .max + end + + sig { returns(T.class_of(Dependabot::Version)) } + def version_class + dependency.version_class + end + + sig { returns(T.class_of(Dependabot::Requirement)) } + def requirement_class + dependency.requirement_class + end + + sig { returns(String) } + def version_regex + Dependabot::Nub::Version::VERSION_PATTERN + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/update_checker/vulnerability_auditor.rb b/nub/lib/dependabot/nub/update_checker/vulnerability_auditor.rb new file mode 100644 index 00000000000..7631e2bd3ee --- /dev/null +++ b/nub/lib/dependabot/nub/update_checker/vulnerability_auditor.rb @@ -0,0 +1,221 @@ +# typed: strict +# frozen_string_literal: true + +require "sorbet-runtime" +require "stringio" + +require "dependabot/dependency" +require "dependabot/errors" +require "dependabot/logger" +require "dependabot/nub/file_parser" +require "dependabot/nub/helpers" +require "dependabot/nub/native_helpers" +require "dependabot/nub/update_checker" +require "dependabot/nub/update_checker/dependency_files_builder" +require "dependabot/shared_helpers" + +module Dependabot + module Nub + class UpdateChecker < Dependabot::UpdateCheckers::Base + class VulnerabilityAuditor + extend T::Sig + + sig do + params( + dependency_files: T::Array[Dependabot::DependencyFile], + credentials: T::Array[Dependabot::Credential] + ) + .void + end + def initialize(dependency_files:, credentials:) + @dependency_files = dependency_files + @credentials = credentials + end + + # rubocop:disable Metrics/MethodLength + # Finds any dependencies in the `package-lock.json` or `npm-shrinkwrap.json` that have + # a subdependency on the given dependency that is locked to a vuln version range. + # + # NOTE: yarn is currently not supported. + # + # @param dependency [Dependabot::Dependency] the dependency to check + # @param security_advisories [Array] advisories for the dependency + # @return [Hash>]>] the audit results + # * :dependency_name [String] the name of the dependency + # * :fix_available [Boolean] whether a fix is available + # * :current_version [String] the version of the dependency + # * :target_version [String] the version of the dependency after the fix + # * :fix_updates [Array>] a list of dependencies to update in order to fix + # * :dependency_name [String] the name of the blocking dependency + # * :current_version [String] the current version of the blocking dependency + # * :target_version [String] the target version of the blocking dependency + # * :top_level_ancestors [Array] the names of top-level dependencies with a transitive + # dependency on the blocking dependency + # * :top_level_ancestors [Array] the names of all top-level dependencies with a transitive + # dependency on the dependency + # * :explanation [String] an explanation for why the project failed the vulnerability auditor run + sig do + params( + dependency: Dependabot::Dependency, + security_advisories: T::Array[Dependabot::SecurityAdvisory] + ) + .returns(T::Hash[String, T.untyped]) + end + def audit(dependency:, security_advisories:) + Dependabot.logger.info("VulnerabilityAuditor: starting audit") + + fix_unavailable = { + "dependency_name" => dependency.name, + "fix_available" => false, + "fix_updates" => [], + "top_level_ancestors" => [] + } + + SharedHelpers.in_a_temporary_directory do + dependency_files_builder = DependencyFilesBuilder.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ) + dependency_files_builder.write_temporary_dependency_files + + vuln_versions = security_advisories.map do |a| + { + dependency_name: a.dependency_name, + affected_versions: a.vulnerable_version_strings + } + end + + audit_result = T.cast( + SharedHelpers.run_helper_subprocess( + command: NativeHelpers.helper_path, + function: "npm:vulnerabilityAuditor", + args: [Dir.pwd, vuln_versions] + ), + T::Hash[String, T.untyped] + ) + + validation_result = validate_audit_result(audit_result, security_advisories) + if validation_result != :viable + Dependabot.logger.info("VulnerabilityAuditor: audit result not viable: #{validation_result}") + fix_unavailable["explanation"] = explain_fix_unavailable(validation_result, dependency) + return fix_unavailable + end + + Dependabot.logger.info("VulnerabilityAuditor: audit result viable") + audit_result + end + rescue SharedHelpers::HelperSubprocessFailed => e + log_helper_subprocess_failure(dependency, e) + T.must(fix_unavailable) + end + # rubocop:enable Metrics/MethodLength + + private + + sig { returns(T::Array[Dependabot::DependencyFile]) } + attr_reader :dependency_files + + sig { returns(T::Array[Dependabot::Credential]) } + attr_reader :credentials + + sig { params(validation_result: Symbol, dependency: Dependabot::Dependency).returns(String) } + def explain_fix_unavailable(validation_result, dependency) + case validation_result + when :fix_unavailable, :dependency_still_vulnerable, :downgrades_dependencies + "No patched version available for #{dependency.name}" + when :fix_incomplete + "The lockfile might be out of sync?" + else + raise "Unexpected validation result: #{validation_result}" + end + end + + sig do + params( + audit_result: T::Hash[String, T.untyped], + security_advisories: T::Array[Dependabot::SecurityAdvisory] + ).returns(Symbol) + end + def validate_audit_result(audit_result, security_advisories) + return :fix_unavailable unless audit_result["fix_available"] + return :dependency_still_vulnerable if dependency_still_vulnerable?(audit_result, security_advisories) + return :downgrades_dependencies if downgrades_dependencies?(audit_result) + return :fix_incomplete if fix_incomplete?(audit_result) + + :viable + end + + sig do + params( + audit_result: T::Hash[String, T.untyped], + security_advisories: T::Array[Dependabot::SecurityAdvisory] + ) + .returns(T::Boolean) + end + def dependency_still_vulnerable?(audit_result, security_advisories) + # vulnerable dependency is removed if the target version is nil + return false unless audit_result["target_version"] + + version = Version.new(audit_result["target_version"]) + security_advisories.any? { |a| a.vulnerable?(version) } + end + + sig { params(audit_result: T::Hash[String, T.untyped]).returns(T::Boolean) } + def downgrades_dependencies?(audit_result) + return true if downgrades_version?(audit_result["current_version"], audit_result["target_version"]) + + audit_result["fix_updates"].any? do |update| + downgrades_version?(update["current_version"], update["target_version"]) + end + end + + sig do + params( + current_version: T.nilable(T.any(String, Integer, Gem::Version)), + target_version: T.nilable(T.any(String, Integer, Gem::Version)) + ) + .returns(T::Boolean) + end + def downgrades_version?(current_version, target_version) + return false unless target_version + + current = Version.new(current_version) + target = Version.new(target_version) + current > target + end + + sig { params(audit_result: T::Hash[String, T.untyped]).returns(T::Boolean) } + def fix_incomplete?(audit_result) + audit_result["fix_updates"].any? { |update| !update.key?("target_version") } || + audit_result["fix_updates"].empty? + end + + sig do + params( + dependency: Dependabot::Dependency, + error: Dependabot::SharedHelpers::HelperSubprocessFailed + ).void + end + def log_helper_subprocess_failure(dependency, error) + # See `Dependabot::SharedHelpers.run_helper_subprocess` for details on error context + context = error.error_context + function = T.cast(context[:function], T.nilable(String)) + time_taken = T.cast(context[:time_taken], T.nilable(Float)) + + builder = ::StringIO.new + builder << "VulnerabilityAuditor: " + builder << "#{function} " if function + builder << "failed" + builder << " after #{time_taken.truncate(2)}s" if time_taken + builder << " while auditing #{dependency.name}: " + builder << error.message + builder << "\n" << context[:trace] + + msg = builder.string + Dependabot.logger.info(msg) # TODO: is this the right log level? + end + end + end + end +end diff --git a/nub/lib/dependabot/nub/version.rb b/nub/lib/dependabot/nub/version.rb new file mode 100644 index 00000000000..7a658b95aca --- /dev/null +++ b/nub/lib/dependabot/nub/version.rb @@ -0,0 +1,137 @@ +# typed: strict +# frozen_string_literal: true + +require "dependabot/version" +require "dependabot/utils" +require "sorbet-runtime" + +# JavaScript pre-release versions use 1.0.1-rc1 syntax, which Gem::Version +# converts into 1.0.1.pre.rc1. We override the `to_s` method to stop that +# alteration. +# +# See https://semver.org/ for details of node's version syntax. + +module Dependabot + module Nub + class Version < Dependabot::Version + extend T::Sig + + sig { returns(T.nilable(String)) } + attr_reader :build_info + + # These are possible npm versioning tags that can be used in place of a version. + # See https://docs.npmjs.com/cli/v10/commands/npm-dist-tag#purpose for more details. + VERSION_TAGS = T.let( + [ + "alpha", # Alpha version, early testing phase + "beta", # Beta version, more stable than alpha + "canary", # Canary version, often used for cutting-edge builds + "dev", # Development version, ongoing development + "experimental", # Experimental version, unstable and new features + "latest", # Latest stable version, used by npm to identify the current version of a package + "legacy", # Legacy version, older version maintained for compatibility + "next", # Next version, used by some projects to identify the upcoming version + "nightly", # Nightly build, daily builds often including latest changes + "rc", # Release candidate, potential final version + "release", # General release version + "stable" # Stable version, thoroughly tested and stable + ].freeze.map(&:freeze), + T::Array[String] + ) + + VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String) + ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/ + + sig { override.params(version: VersionParameter).returns(T::Boolean) } + def self.correct?(version) + version = version.gsub(/^v/, "") if version.is_a?(String) + + return false if version.nil? + + version.to_s.match?(ANCHORED_VERSION_PATTERN) + end + + sig { params(version: VersionParameter).returns(VersionParameter) } + def self.semver_for(version) + # The next two lines are to guard against improperly formatted + # versions in a lockfile, such as an empty string or additional + # characters. NPM/yarn fixes these when running an update, so we can + # safely ignore these versions. + return if version == "" + return unless correct?(version) + + version + end + + sig { override.params(version: VersionParameter).void } + def initialize(version) + version = clean_version(version) + + @version_string = T.let(version.to_s, String) + + @build_info = T.let(nil, T.nilable(String)) + + version, @build_info = version.to_s.split("+") if version.to_s.include?("+") + + super(T.must(version)) + end + + sig { params(version: VersionParameter).returns(VersionParameter) } + def clean_version(version) + # Check if version is a string before attempting to match + if version.is_a?(String) + # Matches @ followed by x.y.z (digits separated by dots) + if (match = version.match(/@(\d+\.\d+\.\d+)/)) + version = match[1] # Just "4.5.3" + end + version = version&.gsub(/^v/, "") + end + + version + end + + sig { override.params(version: VersionParameter).returns(Dependabot::Nub::Version) } + def self.new(version) + T.cast(super, Dependabot::Nub::Version) + end + + sig { returns(Integer) } + def major + @major ||= T.let(segments[0].to_i, T.nilable(Integer)) + end + + sig { returns(Integer) } + def minor + @minor ||= T.let(segments[1].to_i, T.nilable(Integer)) + end + + sig { returns(Integer) } + def patch + @patch ||= T.let(segments[2].to_i, T.nilable(Integer)) + end + + sig { params(other: Dependabot::Nub::Version).returns(T::Boolean) } + def backwards_compatible_with?(other) + case major + when 0 + self == other + else + major == other.major && minor >= other.minor + end + end + + sig { override.returns(String) } + def to_s + @version_string + end + + sig { override.returns(String) } + def inspect + "#<#{self.class} #{@version_string}>" + end + end + end +end + +Dependabot::Utils + .register_version_class("nub", Dependabot::Nub::Version) diff --git a/nub/lib/dependabot/nub/version_selector.rb b/nub/lib/dependabot/nub/version_selector.rb new file mode 100644 index 00000000000..554727a69f2 --- /dev/null +++ b/nub/lib/dependabot/nub/version_selector.rb @@ -0,0 +1,11 @@ +# typed: strong +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/version_selector" + +# Engine-constraint selection is format-agnostic; delegate to npm_and_yarn. +module Dependabot + module Nub + VersionSelector = Dependabot::NpmAndYarn::VersionSelector + end +end diff --git a/nub/script/ci-test b/nub/script/ci-test new file mode 100755 index 00000000000..2999414d424 --- /dev/null +++ b/nub/script/ci-test @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +bundle install +bundle exec turbo_tests2 --verbose + +# Should we only run these on one of the CI_NODE_INDEX's? +cd /opt/nub && npm run lint && cd - +cd /opt/nub && npm test && cd - diff --git a/nub/spec/dependabot/nub/file_fetcher_spec.rb b/nub/spec/dependabot/nub/file_fetcher_spec.rb new file mode 100644 index 00000000000..8e67c3acc0b --- /dev/null +++ b/nub/spec/dependabot/nub/file_fetcher_spec.rb @@ -0,0 +1,214 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/file_fetchers" +require "dependabot/nub" +require_common_spec "file_fetchers/shared_examples_for_file_fetchers" + +RSpec.describe Dependabot::Nub::FileFetcher do + let(:json_header) { { "content-type" => "application/json" } } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:directory) { "/" } + let(:url) { "https://api.github.com/repos/gocardless/bump/contents/" } + let(:file_fetcher_instance) do + described_class.new(source: source, credentials: credentials) + end + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: directory + ) + end + + before do + allow(file_fetcher_instance).to receive(:commit).and_return("sha") + + stub_request(:get, File.join(url, "?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: "[]", + headers: json_header + ) + + stub_request(:get, File.join(url, "package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_content.json"), + headers: json_header + ) + end + + context "with a nub.lock but no package-lock.json file" do + before do + stub_request(:get, url + "?ref=sha") + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "contents_js_nub.json"), + headers: json_header + ) + stub_request(:get, File.join(url, "package-lock.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return(status: 404) + stub_request(:get, File.join(url, "nub.lock?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "nub_lock_content.json"), + headers: json_header + ) + end + + describe "fetching and parsing the nub.lock" do + before do + allow(Dependabot::Experiments).to receive(:enabled?) + end + + it "fetches and parses the nub.lock" do + expect(file_fetcher_instance.files.map(&:name)) + .to match_array(%w(package.json nub.lock)) + expect(file_fetcher_instance.ecosystem_versions) + .to match({ package_managers: { "nub" => an_instance_of(Integer) } }) + end + end + end + + context "with a path dependency" do + before do + stub_request(:get, File.join(url, "package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_with_path_content.json"), + headers: json_header + ) + end + + context "with a bad package.json" do + before do + stub_request(:get, File.join(url, "package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "gemfile_content.json"), + headers: json_header + ) + end + + it "raises a DependencyFileNotParseable error" do + expect { file_fetcher_instance.files } + .to raise_error(Dependabot::DependencyFileNotParseable) do |error| + expect(error.file_name).to eq("package.json") + end + end + end + + context "with a bad dependencies object" do + before do + stub_request(:get, File.join(url, "package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_with_dependency_arrays.json"), + headers: json_header + ) + end + + it "raises a DependencyFileNotParseable error" do + expect { file_fetcher_instance.files } + .to raise_error(Dependabot::DependencyFileNotParseable) do |error| + expect(error.file_name).to eq("package.json") + end + end + end + + context "when path is fetchable" do + before do + stub_request(:get, File.join(url, "deps/etag/package.json?ref=sha")) + .with(headers: { "Authorization" => "token token" }) + .to_return( + status: 200, + body: fixture("github", "package_json_content.json"), + headers: json_header + ) + end + + it "fetches package.json from path dependency" do + expect(file_fetcher_instance.files.count).to eq(2) + expect(file_fetcher_instance.files.map(&:name)) + .to include("deps/etag/package.json") + path_file = file_fetcher_instance.files + .find { |f| f.name == "deps/etag/package.json" } + expect(path_file.support_file?).to be(true) + end + end + end + + context "with package.json file just including a dummy string" do + before do + allow(file_fetcher_instance).to receive(:commit).and_return("sha") + stub_request(:get, File.join(url, "package.json?ref=sha")) + .to_return( + status: 200, + body: fixture_to_response("projects/javascript/package_json_faked", "package.json"), + headers: json_header + ) + end + + it "raises a DependencyFileNotParseable error" do + expect { file_fetcher_instance.files } + .to raise_error(Dependabot::DependencyFileNotParseable) do |error| + expect(error.file_name).to eq("package.json") + end + end + end + + context "with packageManager field not in x.y.z format" do + before do + allow(file_fetcher_instance).to receive(:commit).and_return("sha") + stub_request(:get, File.join(url, "package.json?ref=sha")) + .to_return( + status: 200, + body: fixture_to_response("projects/javascript/package_manager_unparseable", "package.json"), + headers: json_header + ) + end + + it "still fetches package.json fine" do + expect(file_fetcher_instance.files.count).to eq(1) + end + end + + context "with lockfileVersion not in integer format" do + before do + allow(file_fetcher_instance).to receive(:commit).and_return("sha") + stub_request(:get, File.join(url, "package.json?ref=sha")) + .to_return( + status: 200, + body: fixture_to_response("projects/javascript/lockfile_version_unparseable", "package.json"), + headers: json_header + ) + end + + it "still fetches files" do + expect(file_fetcher_instance.files.count).to eq(1) + end + end +end + +def fixture_to_response(dir, file) + JSON.dump({ "content" => Base64.encode64(fixture(dir, file)) }) +end diff --git a/nub/spec/dependabot/nub/file_parser/lockfile_parser_spec.rb b/nub/spec/dependabot/nub/file_parser/lockfile_parser_spec.rb new file mode 100644 index 00000000000..81e32b71eff --- /dev/null +++ b/nub/spec/dependabot/nub/file_parser/lockfile_parser_spec.rb @@ -0,0 +1,60 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" + +RSpec.describe Dependabot::Nub::FileParser::LockfileParser do + subject(:lockfile_parser) do + described_class.new(dependency_files: dependency_files) + end + + describe "#parse" do + subject(:dependencies) { lockfile_parser.parse } + + # nub.lock is a pnpm-lock v9 document; it is parsed via the shared pnpm parseLockfile helper. + context "when dealing with a valid nub.lock" do + let(:dependency_files) { project_dependency_files("nub/simple_v1") } + + it "parses the top-level dependencies" do + expect(dependencies.find { |d| d.name == "fetch-factory" }).to have_attributes( + name: "fetch-factory", + version: "0.0.1" + ) + expect(dependencies.find { |d| d.name == "etag" }).to have_attributes( + name: "etag", + version: "1.8.1" + ) + end + + it "parses transitive dependencies from the snapshots section" do + expect(dependencies.find { |d| d.name == "lodash" }).to have_attributes( + name: "lodash", + version: "3.10.1" + ) + end + end + + context "when the lockfile is not parseable pnpm-lock v9" do + let(:dependency_files) do + [ + Dependabot::DependencyFile.new( + name: "package.json", + content: '{"dependencies": {"etag": "^1.0.0"}}' + ), + Dependabot::DependencyFile.new( + name: "nub.lock", + content: ":\n not: valid: pnpm: lock: [" + ) + ] + end + + it "raises a DependencyFileNotParseable error naming nub.lock" do + expect { dependencies } + .to raise_error(Dependabot::DependencyFileNotParseable) do |error| + expect(error.file_name).to eq("nub.lock") + end + end + end + end +end diff --git a/nub/spec/dependabot/nub/file_parser_spec.rb b/nub/spec/dependabot/nub/file_parser_spec.rb new file mode 100644 index 00000000000..37d2e431879 --- /dev/null +++ b/nub/spec/dependabot/nub/file_parser_spec.rb @@ -0,0 +1,136 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" + +RSpec.describe Dependabot::Nub::FileParser do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: "/" + ) + end + let(:parser) do + described_class.new( + dependency_files: files, + source: source, + credentials: credentials + ) + end + + describe "inheritance" do + require_common_spec "file_parsers/shared_examples_for_file_parsers" + + it_behaves_like "a dependency file parser" + end + + describe "parse" do + subject(:dependencies) { parser.parse } + + describe "top level dependencies" do + subject(:top_level_dependencies) { dependencies.select(&:top_level?) } + + context "with no lockfile" do + let(:files) { project_dependency_files("javascript/exact_version_requirements_no_lockfile") } + + its(:length) { is_expected.to eq(3) } + + describe "the first dependency" do + subject { top_level_dependencies.first } + + it { is_expected.to be_a(Dependabot::Dependency) } + its(:name) { is_expected.to eq("chalk") } + its(:version) { is_expected.to eq("0.3.0") } + end + end + + context "with no lockfile, and non exact requirements" do + let(:files) { project_dependency_files("javascript/file_version_requirements_no_lockfile") } + + its(:length) { is_expected.to eq(0) } + end + end + end + + describe "missing package.json manifest file" do + let(:child_class) do + Class.new(described_class) do + def check_required_files + %w(manifest).each do |filename| + next if get_original_file(filename) + + raise Dependabot::DependencyFileNotFound.new( + nil, + "package.json not found." + ) + end + end + end + end + let(:parser_instance) do + child_class.new(dependency_files: files, source: source) + end + let(:source) do + Dependabot::Source.new( + provider: "github", + repo: "gocardless/bump", + directory: "/" + ) + end + + let(:gemfile) do + Dependabot::DependencyFile.new( + content: "a", + name: "manifest", + directory: "/path/to" + ) + end + let(:files) { [gemfile] } + + describe ".new" do + context "when the required file is present" do + let(:files) { [gemfile] } + + it "doesn't raise" do + expect { parser_instance }.not_to raise_error + end + end + + context "when the required file is missing" do + let(:files) { [] } + + it "raises" do + expect { parser_instance }.to raise_error(Dependabot::DependencyFileNotFound) + end + end + end + + describe "#get_original_file" do + subject { parser_instance.send(:get_original_file, filename) } + + context "when the requested file is present" do + let(:filename) { "manifest" } + + it { is_expected.to eq(gemfile) } + end + + context "when the requested file is not present" do + let(:filename) { "package.json" } + + it { is_expected.to be_nil } + end + end + end +end diff --git a/nub/spec/dependabot/nub/file_updater_spec.rb b/nub/spec/dependabot/nub/file_updater_spec.rb new file mode 100644 index 00000000000..fd6e11129f1 --- /dev/null +++ b/nub/spec/dependabot/nub/file_updater_spec.rb @@ -0,0 +1,416 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" + +RSpec.describe Dependabot::Nub::FileUpdater do + let(:repo_contents_path) { nil } + let(:tmp_path) { Dependabot::Utils::BUMP_TMP_DIR_PATH } + let(:source) { nil } + let(:previous_requirements) do + [{ + file: "package.json", + requirement: "^0.0.1", + groups: ["dependencies"], + source: source + }] + end + let(:requirements) do + [{ + file: "package.json", + requirement: "^0.0.2", + groups: ["dependencies"], + source: nil + }] + end + let(:previous_version) { "0.0.1" } + let(:version) { "0.0.2" } + let(:dependency_name) { "fetch-factory" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: version, + previous_version: previous_version, + requirements: requirements, + previous_requirements: previous_requirements, + package_manager: "nub" + ) + end + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com" + } + )] + end + let(:dependencies) { [dependency] } + let(:updater) do + described_class.new( + dependency_files: files, + dependencies: dependencies, + credentials: credentials, + repo_contents_path: repo_contents_path + ) + end + + before do + FileUtils.mkdir_p(tmp_path) + end + + describe "#updated_dependency_files" do + subject(:updated_files) { updater.updated_dependency_files } + + let(:updated_package_json) { updated_files.find { |f| f.name == "package.json" } } + let(:updated_nub_lock) { updated_files.find { |f| f.name == "nub.lock" } } + + context "without a lockfile" do + let(:files) { project_dependency_files("javascript/simple_manifest") } + + its(:length) { is_expected.to eq(1) } + + context "when nothing has changed" do + let(:requirements) { previous_requirements } + + specify { expect { updated_files }.to raise_error(/No files/) } + end + end + + context "with multiple dependencies" do + let(:files) { project_dependency_files("javascript/multiple_updates") } + let(:repo_contents_path) { build_tmp_repo("javascript/multiple_updates", path: "projects") } + + let(:dependencies) do + [ + Dependabot::Dependency.new( + name: "etag", + version: "1.8.1", + previous_version: "1.0.1", + requirements: [{ + file: "package.json", + requirement: "^1.8.1", + groups: ["dependencies"], + source: nil + }], + previous_requirements: [{ + file: "package.json", + requirement: "^1.0.1", + groups: ["dependencies"], + source: nil + }], + package_manager: "nub" + ), + Dependabot::Dependency.new( + name: "is-number", + version: "4.0.0", + previous_version: "2.0.0", + requirements: [{ + file: "package.json", + requirement: "^4.0.0", + groups: ["dependencies"], + source: nil + }], + previous_requirements: [{ + file: "package.json", + requirement: "^2.0.0", + groups: ["dependencies"], + source: nil + }], + package_manager: "nub" + ) + ] + end + + it "updates both dependencies" do + parsed_package = JSON.parse(updated_package_json.content) + expect(parsed_package["dependencies"]["is-number"]) + .to eq("^4.0.0") + expect(parsed_package["dependencies"]["etag"]) + .to eq("^1.8.1") + end + + context "when dealing with lockfile only update" do + let(:dependencies) do + [ + Dependabot::Dependency.new( + name: "etag", + version: "1.2.0", + previous_version: "1.0.1", + requirements: [{ + file: "package.json", + requirement: "^1.0.1", + groups: ["dependencies"], + source: nil + }], + previous_requirements: [{ + file: "package.json", + requirement: "^1.0.1", + groups: ["dependencies"], + source: nil + }], + package_manager: "nub" + ), + Dependabot::Dependency.new( + name: "is-number", + version: "2.1.0", + previous_version: "2.0.0", + requirements: [{ + file: "package.json", + requirement: "^2.0.0", + groups: ["dependencies"], + source: nil + }], + previous_requirements: [{ + file: "package.json", + requirement: "^2.0.0", + groups: ["dependencies"], + source: nil + }], + package_manager: "nub" + ) + ] + end + + it "updates both dependencies" do + expect(updated_files.map(&:name)) + .to match_array(%w(nub.lock)) + + expect(updated_nub_lock.content) + .to include("is-number@2.1.0") + expect(updated_nub_lock.content) + .to include("etag@1.2.0") + end + + it "updates the lockfile via a single `nub update @` then settles" do + allow(Dependabot::Nub::Helpers).to receive(:run_nub_command).and_call_original + + updated_files + + # One `nub update @ --no-save` pins the chosen versions in the lockfile (nub >= 0.4.1, + # works for transitive deps too); a plain lockfile-only install settles the rest. + expect(Dependabot::Nub::Helpers).to have_received(:run_nub_command).with( + a_string_matching(/^update .+ --lockfile-only --no-save --ignore-scripts$/), + fingerprint: "update --lockfile-only --no-save --ignore-scripts" + ) + expect(Dependabot::Nub::Helpers).to have_received(:run_nub_command).with( + "install --lockfile-only --ignore-scripts", + fingerprint: "install --lockfile-only --ignore-scripts" + ) + end + end + end + + context "with a git dependency" do + let(:dependency_name) { "is-number" } + let(:requirements) do + [{ + requirement: req, + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: ref + } + }] + end + let(:previous_requirements) do + [{ + requirement: old_req, + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: old_ref + } + }] + end + let(:previous_version) { "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8" } + let(:version) { "0c6b15a88bc10cd47f67a09506399dfc9ddc075d" } + + context "when the git ref changes (e.g. a version-tag bump)" do + # The Dependabot-chosen update moves the manifest ref, so PackageJsonUpdater rewrites + # `#2.0.0` -> `#2.1.0` in package.json and nub's lockfile-only install re-resolves the + # git dep to the new tag's commit. This is the supported git-dependency update path. + let(:req) { nil } + let(:ref) { "2.1.0" } + let(:old_req) { nil } + let(:old_ref) { "2.0.0" } + let(:previous_version) { "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8" } + let(:version) { "0024f0f6552b6375712d93a7eadaa48810588736" } + + let(:files) { project_dependency_files("nub/github_dependency_versioned") } + let(:repo_contents_path) { build_tmp_repo("nub/github_dependency_versioned", path: "projects") } + + it "re-resolves the git dependency to the new ref's commit in the lockfile" do + expect(updated_files.map(&:name)).to include("nub.lock") + expect(updated_nub_lock.content) + .to include("codeload.github.com/jonschlinkert/is-number/tar.gz/0024f0f6") + expect(updated_nub_lock.content) + .not_to include("tar.gz/d5ac0584") + end + end + + context "without a requirement or reference (same-branch SHA advance)" do + let(:req) { nil } + let(:ref) { "master" } + let(:old_req) { nil } + let(:old_ref) { "master" } + + let(:files) { project_dependency_files("nub/github_dependency_no_ref") } + let(:repo_contents_path) { build_tmp_repo("nub/github_dependency_no_ref", path: "projects") } + + it "only updates the lockfile" do + skip( + "Unsupported by nub's CLI: the manifest ref is unchanged (master -> master), so " \ + "PackageJsonUpdater produces no manifest edit and nub's conservative lockfile-only " \ + "install keeps the already-locked SHA. Advancing a git dep on the same branch needs " \ + "a nub-side force-re-resolution capability (`update @` / a targeted refresh) " \ + "that nub does not yet expose. Ref-CHANGE git updates DO work (see the context above)." + ) + expect(updated_files.map(&:name)) + .to match_array(%w(nub.lock)) + end + + it "correctly update the lockfiles" do + skip("Unsupported by nub's CLI: same-branch SHA advance, see the sibling example above.") + # nub records a github dependency by its resolved codeload tarball URL (pnpm-v9 form). + expect(updated_nub_lock.content) + .to include("codeload.github.com/jonschlinkert/is-number/tar.gz/98e8ff1") + end + end + end + + context "when a wildcard is specified" do + let(:files) { project_dependency_files("nub/wildcard") } + let(:repo_contents_path) { build_tmp_repo("nub/wildcard", path: "projects") } + + let(:version) { "0.2.0" } + let(:requirements) do + [{ + file: "package.json", + requirement: "*", + groups: ["dependencies"], + source: nil + }] + end + let(:previous_requirements) { requirements } + + it "only updates the lockfiles" do + expect(updated_files.map(&:name)) + .to match_array(%w(nub.lock)) + + expect(updated_nub_lock.content) + .to include("fetch-factory@0.2.0") + end + end + + context "with a transitive (sub-)dependency security update" do + # lodash is a transitive dep of fetch-factory, not present in package.json. Dependabot drives + # these for security advisories; `nub update lodash@` bumps it in the lockfile only. + let(:files) { project_dependency_files("nub/transitive_update") } + let(:repo_contents_path) { build_tmp_repo("nub/transitive_update", path: "projects") } + let(:dependencies) do + [Dependabot::Dependency.new( + name: "lodash", + version: "4.17.21", + previous_version: "3.10.1", + requirements: [], + previous_requirements: [], + package_manager: "nub" + )] + end + + it "bumps the transitive dependency in the lockfile" do + expect(updated_files.map(&:name)).to match_array(%w(nub.lock)) + expect(updated_nub_lock.content).to include("lodash@4.17.21") + expect(updated_nub_lock.content).not_to include("lodash@3.10.1") + end + end + end + + describe "without a package.json file" do + let(:child_class) do + Class.new(described_class) do + def check_required_files + %w(manifest).each do |filename| + next if get_original_file(filename) + + raise Dependabot::DependencyFileNotFound.new( + nil, + "package.json not found." + ) + end + end + end + end + let(:updater_instance) do + child_class.new( + dependency_files: files, + dependencies: [dependency], + credentials: [{ + "type" => "git_source", + "host" => "github.com" + }] + ) + end + + let(:manifest) do + Dependabot::DependencyFile.new( + content: "a", + name: "manifest", + directory: "/path/to" + ) + end + let(:dependency) do + Dependabot::Dependency.new( + name: "business", + version: "1.5.0", + package_manager: "bundler", + requirements: + [{ file: "manifest", requirement: "~> 1.4.0", groups: [], source: nil }] + ) + end + let(:files) { [manifest] } + + describe "new file updater" do + subject { -> { updater_instance } } + + context "when the required file is present" do + let(:files) { [manifest] } + + it "doesn't raise" do + expect { updater_instance }.not_to raise_error + end + end + + context "when the required file is missing" do + let(:files) { [] } + + it "raises" do + expect { updater_instance }.to raise_error(Dependabot::DependencyFileNotFound) + end + end + end + + describe "#get_original_file" do + subject { updater_instance.send(:get_original_file, filename) } + + context "when the requested file is present" do + let(:filename) { "manifest" } + + it { is_expected.to eq(manifest) } + end + + context "when the requested file is not present" do + let(:filename) { "package.json" } + + it { is_expected.to be_nil } + end + end + end +end diff --git a/nub/spec/dependabot/nub/metadata_finder_spec.rb b/nub/spec/dependabot/nub/metadata_finder_spec.rb new file mode 100644 index 00000000000..d526023ddd4 --- /dev/null +++ b/nub/spec/dependabot/nub/metadata_finder_spec.rb @@ -0,0 +1,704 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub/metadata_finder" +require_common_spec "metadata_finders/shared_examples_for_metadata_finders" + +RSpec.describe Dependabot::Nub::MetadataFinder do + subject(:finder) do + described_class.new(dependency: dependency, credentials: credentials) + end + + let(:dependency_name) { "etag" } + + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.6.0", + requirements: [ + { file: "package.json", requirement: "^1.0", groups: [], source: nil } + ], + package_manager: "nub" + ) + end + + it_behaves_like "a dependency metadata finder" + + describe "#source_url" do + subject(:source_url) { finder.source_url } + + let(:npm_url) { "https://registry.npmjs.org/etag" } + + before do + stub_request(:get, npm_url + "/latest") + .to_return(status: 200, body: npm_latest_version_response) + stub_request(:get, npm_url) + .to_return(status: 200, body: npm_all_versions_response) + stub_request(:get, "https://example.come/status").to_return( + status: 200, + body: "Not GHES", + headers: {} + ) + stub_request(:get, "https://jshttp/status").to_return(status: 404) + end + + context "when dealing with a git dependency" do + let(:npm_all_versions_response) { nil } + let(:npm_latest_version_response) { nil } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8", + requirements: [{ + file: "package.json", + requirement: nil, + groups: [], + source: { + type: "git", + url: "https://github.com/jshttp/etag", + branch: nil, + ref: "master" + } + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + + it "doesn't hit npm" do + source_url + expect(WebMock).not_to have_requested(:get, npm_url) + end + end + + context "when there is a github link in the npm response" do + let(:npm_latest_version_response) do + fixture("npm_responses", "etag-1.0.0.json") + end + let(:npm_all_versions_response) do + fixture("npm_responses", "etag.json") + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + + it "caches the call to npm" do + 2.times { source_url } + expect(WebMock) + .to have_requested(:get, npm_url + "/latest").once + expect(WebMock) + .not_to have_requested(:get, npm_url) + end + + context "with a monorepo that specifies a directory" do + let(:npm_latest_version_response) do + fixture("npm_responses", "react-dom-with-dir.json") + end + let(:npm_all_versions_response) do + fixture("npm_responses", "react-dom.json") + end + + it "includes details of the directory" do + skip( + "monorepo source-directory extraction needs the GitHub default-branch stub the " \ + "npm_and_yarn spec sets up; the metadata_finder logic is present but the spec " \ + "harness for it is a follow-up." + ) + expect(source_url).to eq( + "https://github.com/facebook/react/tree/HEAD/packages/react-dom" + ) + end + end + end + + context "when there is a bitbucket link in the npm response" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) do + fixture("npm_responses", "npm_response_bitbucket.json") + end + + it { is_expected.to eq("https://bitbucket.org/jshttp/etag") } + + it "caches the call to npm" do + 2.times { source_url } + expect(WebMock) + .to have_requested(:get, npm_url + "/latest").once + expect(WebMock) + .to have_requested(:get, npm_url).once + end + end + + context "when there's a link without the expected structure" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) do + fixture("npm_responses", "npm_response_string_link.json") + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + + it "caches the call to npm" do + 2.times { source_url } + expect(WebMock).to have_requested(:get, npm_url).once + end + end + + context "when there's a link using GitHub shorthand" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) do + fixture("npm_responses", "npm_response_string_shorthand.json") + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + + it "caches the call to npm" do + 2.times { source_url } + expect(WebMock).to have_requested(:get, npm_url).once + end + end + + context "when there isn't a source link in the npm response" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) do + fixture("npm_responses", "npm_response_no_source.json") + end + + it { is_expected.to be_nil } + + it "caches the call to npm" do + 2.times { source_url } + expect(WebMock).to have_requested(:get, npm_url).once + end + end + + context "when the npm link resolves to a redirect" do + let(:redirect_url) { "https://registry.npmjs.org/eTag" } + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) { fixture("npm_responses", "etag.json") } + + before do + stub_request(:get, npm_url) + .to_return(status: 302, headers: { "Location" => redirect_url }) + stub_request(:get, redirect_url) + .to_return(status: 200, body: npm_all_versions_response) + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + end + + context "when the npm link 404s" do + before do + stub_request(:get, npm_url).to_return(status: 404) + stub_request(:get, npm_url + "/latest").to_return(status: 404) + stub_request(:get, npm_url + "/latest").to_return(status: 404) + end + + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) { fixture("npm_responses", "etag.json") } + + # Not an ideal error, but this should never happen + specify { expect { finder.source_url }.to raise_error(JSON::ParserError) } + end + + context "when dealing with a scoped package name" do + before do + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag/latest") + .to_return(status: 200, body: npm_latest_version_response) + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag") + .to_return(status: 200, body: npm_all_versions_response) + end + + let(:dependency_name) { "@etag/etag" } + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) { fixture("npm_responses", "etag.json") } + + it "requests the escaped name" do + finder.source_url + + expect(WebMock) + .to have_requested(:get, "https://registry.npmjs.org/@etag%2Fetag") + end + + context "when registry is private" do + before do + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag") + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: npm_all_versions_response) + end + + context "with credentials" do + let(:credentials) do + [ + Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), + Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "registry.npmjs.org", + "token" => "secret_token" + } + ) + ] + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + end + + context "without credentials" do + before do + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + end + + it { is_expected.to be_nil } + end + end + + context "when dependency is hosted on gemfury" do + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/@etag%2Fetag") + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request( + :get, "https://npm.fury.io/dependabot/@etag%2Fetag/latest" + ).to_return(status: 404, body: '{"error":"Not found"}') + stub_request( + :get, "https://npm.fury.io/dependabot/@etag%2Fetag/latest" + ).to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://npm.fury.io/dependabot/@etag%2Fetag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0", + requirements: [{ + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://npm.fury.io/dependabot" + } + }], + package_manager: "nub" + ) + end + + context "with credentials" do + let(:credentials) do + [ + Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), + Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token" + } + ) + ] + end + + it { is_expected.to eq("https://github.com/jshttp/etag") } + end + + context "without credentials" do + before do + stub_request( + :get, "https://registry.npmjs.org/@etag%2Fetag/latest" + ).with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + stub_request( + :get, "https://registry.npmjs.org/@etag%2Fetag/latest" + ).with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + stub_request(:get, "https://registry.npmjs.org/@etag%2Fetag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + end + + it { is_expected.to be_nil } + end + end + end + + context "when multiple sources are detected" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) { nil } + let(:dependency_name) { "@etag/etag" } + + let(:credentials) do + [ + Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), + Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token" + } + ) + ] + end + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0", + requirements: [ + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://registry.npmjs.org" + } + }, + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://npm.fury.io/dependabot" + } + } + ], + package_manager: "nub" + ) + end + + before do + stub_request( + :get, "https://npm.fury.io/dependabot/@etag%2Fetag/latest" + ).to_return(status: 404, body: '{"error":"Not found"}').times(2) + + stub_request(:get, "https://npm.fury.io/dependabot/@etag%2Fetag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return( + status: 200, + body: fixture("gemfury_responses", "gemfury_response_etag.json") + ) + end + + it "prefers to fetch metadata from the private registry" do + expect(source_url).to eq("https://github.com/jshttp/etag") + end + end + + context "when there is a space in the package resolved URL" do + let(:npm_latest_version_response) { nil } + let(:npm_all_versions_response) { nil } + let(:dependency_name) { "@etag/etag" } + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0", + requirements: [ + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://npm.example.com/registry with spaces" + } + } + ], + package_manager: "nub" + ) + end + + before do + # the URL reported above has spaces, but we only stub the escaped versions + stub_request( + :get, "https://npm.example.com/registry%20with%20spaces/@etag%2Fetag/latest" + ).to_return(status: 404, body: '{"error":"Not found"}').times(2) + + stub_request(:get, "https://npm.example.com/registry%20with%20spaces/@etag%2Fetag") + .to_return( + status: 200, + body: fixture("gemfury_responses", "gemfury_response_etag.json") + ) + end + + it "escapes the spaces before querying the content" do + expect(source_url).to eq("https://github.com/jshttp/etag") + end + end + end + + describe "#homepage_url" do + subject(:homepage_url) { finder.homepage_url } + + let(:npm_url) { "https://registry.npmjs.org/etag" } + + before do + stub_request(:get, npm_url + "/latest") + .to_return(status: 200, body: npm_latest_version_response) + stub_request(:get, npm_url) + .to_return(status: 200, body: npm_all_versions_response) + end + + context "when there is a homepage link in the npm response" do + let(:npm_all_versions_response) do + fixture("npm_responses", "npm_response_no_source.json") + end + let(:npm_latest_version_response) { nil } + + it "returns the specified homepage" do + expect(homepage_url).to eq("https://example.come/jshttp/etag") + end + end + end + + describe "#maintainer_changes" do + subject(:maintainer_changes) { finder.maintainer_changes } + + let(:npm_url) { "https://registry.npmjs.org/etag" } + let(:npm_all_versions_response) do + fixture("npm_responses", "etag.json") + end + + before do + stub_request(:get, npm_url) + .to_return(status: 200, body: npm_all_versions_response) + end + + context "when the user that pushed this version has pushed before" do + it { is_expected.to be_nil } + end + + context "when the user that pushed this version hasn't pushed before" do + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.6.0", + previous_version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "gives details of the new releaser" do + expect(maintainer_changes).to eq( + "This version was pushed to npm by " \ + "[dougwilson](https://www.npmjs.com/~dougwilson), a new releaser " \ + "for etag since your current version." + ) + end + end + + context "when the maintainer name contains spaces" do + let(:dependency_name) { "npm-package-json-lint" } + let(:npm_url) { "https://registry.npmjs.org/npm-package-json-lint" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "10.0.0", + previous_version: "9.0.0", + requirements: [{ + file: "package.json", + requirement: "^10.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:npm_all_versions_response) do + fixture("npm_responses", "npm-package-json-lint.json") + end + + it "properly URL-encodes the maintainer name in the link" do + expect(maintainer_changes).to eq( + "This version was pushed to npm by " \ + "[GitHub Actions](https://www.npmjs.com/~GitHub%20Actions), a new releaser " \ + "for npm-package-json-lint since your current version." + ) + end + end + end + + describe "#dependency_url" do + subject(:dependency_url) { finder.send(:dependency_url) } + + context "when no source information is available" do + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.6.0", + requirements: [ + { file: "package.json", requirement: "^1.0", groups: [], source: nil } + ], + package_manager: "nub" + ) + end + + context "without credentials" do + let(:credentials) { [] } + + it "falls back to public npm registry" do + expect(dependency_url).to eq("https://registry.npmjs.org/etag") + end + end + + context "with replaces-base credential" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "jfrogghdemo.jfrog.io/artifactory/api/npm/e2e-tests-dependabot-npm/", + "token" => "secret_token", + "replaces-base" => true + } + )] + end + + it "uses private registry from credentials" do + expect(dependency_url).to eq("https://jfrogghdemo.jfrog.io/artifactory/api/npm/e2e-tests-dependabot-npm/etag") + end + + it "removes trailing slashes from registry URL" do + expect(dependency_url).not_to include("npm//etag") + end + end + + context "with registry URL that has no protocol" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token", + "replaces-base" => true + } + )] + end + + it "adds https protocol" do + expect(dependency_url).to eq("https://npm.fury.io/dependabot/etag") + end + end + + context "with multiple credentials" do + let(:credentials) do + [ + Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "https://npm.fury.io/dependabot", + "token" => "secret_token", + "replaces-base" => true + } + ), + Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "another.registry.com", + "token" => "another_secret_token" + } + ) + ] + end + + it "takes precedence over other credentials" do + expect(dependency_url).to eq("https://npm.fury.io/dependabot/etag") + end + end + + context "with scoped dependency name" do + let(:dependency_name) { "@babel/core" } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token", + "replaces-base" => true + } + )] + end + + it "escapes dependency name properly" do + expect(dependency_url).to eq("https://npm.fury.io/dependabot/@babel%2Fcore") + end + end + end + + context "when source information is available from lockfile" do + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.6.0", + requirements: [ + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { type: "registry", url: "https://npm.fury.io/dependabot" } + } + ], + package_manager: "nub" + ) + end + + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "different.registry.com", + "token" => "secret_token", + "replaces-base" => true + } + )] + end + + it "uses source from lockfile, not credentials" do + expect(dependency_url).to eq("https://npm.fury.io/dependabot/etag") + end + end + end +end diff --git a/nub/spec/dependabot/nub/nub_package_manager_spec.rb b/nub/spec/dependabot/nub/nub_package_manager_spec.rb new file mode 100644 index 00000000000..36c36251019 --- /dev/null +++ b/nub/spec/dependabot/nub/nub_package_manager_spec.rb @@ -0,0 +1,52 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" + +RSpec.describe Dependabot::Nub::NubPackageManager do + let(:package_manager) do + described_class.new( + detected_version: detected_version, + raw_version: raw_version + ) + end + + let(:detected_version) { "1" } + let(:raw_version) { "1.1.39" } + + describe "#initialize" do + context "when version is a String" do + it "sets the version correctly" do + expect(package_manager.detected_version).to eq(Dependabot::Version.new(detected_version)) + expect(package_manager.version).to eq(Dependabot::Version.new(raw_version)) + end + + it "sets the name correctly" do + expect(package_manager.name).to eq(described_class::NAME) + end + + it "sets the deprecated_versions correctly" do + expect(package_manager.deprecated_versions).to eq( + described_class::DEPRECATED_VERSIONS + ) + end + + it "sets the supported_versions correctly" do + expect(package_manager.supported_versions).to eq(described_class::SUPPORTED_VERSIONS) + end + end + end + + describe "#deprecated?" do + it "returns false" do + expect(package_manager.deprecated?).to be false + end + end + + describe "#unsupported?" do + it "returns false" do + expect(package_manager.unsupported?).to be false + end + end +end diff --git a/nub/spec/dependabot/nub/package/package_details_fetcher_spec.rb b/nub/spec/dependabot/nub/package/package_details_fetcher_spec.rb new file mode 100644 index 00000000000..4b0f04dc6a5 --- /dev/null +++ b/nub/spec/dependabot/nub/package/package_details_fetcher_spec.rb @@ -0,0 +1,147 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/credential" +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/nub/package/package_details_fetcher" +require "dependabot/nub/version" +require "dependabot/nub/requirement" +require "dependabot/package/package_release" +require "dependabot/package/package_language" + +RSpec.describe Dependabot::Nub::Package::PackageDetailsFetcher do + subject(:fetcher) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials + ) + end + + let(:dependency_name) { "react" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "16.6.0", + requirements: [{ + requirement: "^16.0", + file: "package.json", + groups: ["dependencies"], + source: nil + }], + package_manager: "nub" + ) + end + + let(:dependency_files) { [] } + let(:credentials) { [] } + let(:registry_url) { "https://registry.npmjs.org/#{dependency_name}" } + + describe "#fetch" do + subject(:details) { fetcher.fetch } + + before do + stub_request(:get, registry_url).to_return( + status: 200, + body: fixture("npm_responses", "react.json") + ) + end + + context "when version field exists" do + it "includes the requested version in the list" do + expect(details.releases.map(&:version)).to include(Dependabot::Nub::Version.new("16.6.0")) + end + end + + context "when released_at field exists" do + it "parses the correct release date" do + release = details.releases.find { |r| r.version.to_s == "16.6.0" } + expect(release.released_at).to eq(Time.parse("2018-10-23T23:36:06.553Z")) + end + end + + context "when version is deprecated" do + it "marks it as deprecated and includes a reason" do + release = details.releases.find { |r| r.version.to_s == "0.7.1" } + expect(release.details["deprecated"]).to be_a(String) + end + end + + context "when version is not deprecated" do + it "is not marked as yanked and has no reason" do + release = details.releases.find { |r| r.version.to_s == "16.6.0" } + expect(release.yanked).to be(false) + expect(release.yanked_reason).to be_nil + end + end + + it "includes the correct version URL" do + release = details.releases.find { |r| r.version.to_s == "16.6.0" } + expect(release.url).to include("/react/v/16.6.0") + end + + context "when version includes a node engine" do + it "includes the node language with requirement" do + release = details.releases.find { |r| r.version.to_s == "16.6.0" } + expect(release.language&.name).to eq("node") + expect(release.language&.requirement.to_s).to eq(">= 0.10.0") + end + end + + context "when package_type field is defined" do + it "parses the repository type" do + release = details.releases.find { |r| r.version.to_s == "16.6.0" } + expect(release.package_type).to eq("git") + end + end + + context "when version is the latest" do + it "sets latest to true" do + latest_version = details.releases.find(&:latest) + expect(latest_version.version.to_s).to eq("16.6.0") + end + end + + context "when version is not the latest" do + it "sets latest to false" do + release = details.releases.find { |r| r.version.to_s == "16.5.0" } + expect(release.latest).to be(false) + end + end + + context "when the registry raises Excon::Error::Socket" do + context "with a private registry" do + let(:registry_url) { "https://npm.fury.io/dependabot/react" } + + before do + stub_request(:get, registry_url) + .to_raise(Excon::Error::Socket.new(EOFError.new)) + allow_any_instance_of(described_class) # rubocop:disable RSpec/AnyInstance + .to receive(:dependency_registry).and_return("npm.fury.io/dependabot") + allow_any_instance_of(described_class) # rubocop:disable RSpec/AnyInstance + .to receive(:dependency_url).and_return(registry_url) + end + + it "raises PrivateSourceTimedOut" do + expect { fetcher.fetch } + .to raise_error(Dependabot::PrivateSourceTimedOut) do |error| + expect(error.source).to eq("npm.fury.io/") + end + end + end + + context "with the global registry" do + before do + stub_request(:get, registry_url) + .to_raise(Excon::Error::Socket.new(EOFError.new)) + end + + it "re-raises the Excon::Error::Socket" do + expect { fetcher.fetch }.to raise_error(Excon::Error::Socket) + end + end + end + end +end diff --git a/nub/spec/dependabot/nub/package/registry_finder_spec.rb b/nub/spec/dependabot/nub/package/registry_finder_spec.rb new file mode 100644 index 00000000000..a0bb0dc36a8 --- /dev/null +++ b/nub/spec/dependabot/nub/package/registry_finder_spec.rb @@ -0,0 +1,399 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/credential" +require "dependabot/nub/package/registry_finder" + +RSpec.describe Dependabot::Nub::Package::RegistryFinder do + subject(:finder) do + described_class.new( + dependency: dependency, + credentials: credentials, + npmrc_file: npmrc_file + ) + end + + let(:npmrc_file) { nil } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:dependency_name) { "etag" } + let(:requirements) do + [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: source + }] + end + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: requirements, + package_manager: "nub" + ) + end + let(:source) { nil } + + describe "registry_from_rc" do + subject { finder.registry_from_rc(dependency_name) } + + let(:dependency_name) { "some_dep" } + + it { is_expected.to eq("https://registry.npmjs.org") } + + context "with no rc and with credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "http://example.com", + "replaces-base" => true + } + )] + end + + it { is_expected.to eq("http://example.com") } + end + + context "with a global npm registry" do + let(:npmrc_file) { Dependabot::DependencyFile.new(name: ".npmrc", content: "registry=http://example.com") } + + it { is_expected.to eq("http://example.com") } + + context "when dealing with a scoped dependency" do + let(:dependency_name) { "@dependabot/some_dep" } + + it { is_expected.to eq("http://example.com") } + end + end + + context "with a scoped npm registry" do + let(:dependency_name) { "@dependabot/some_dep" } + let(:npmrc_file) { Dependabot::DependencyFile.new(name: ".npmrc", content: "@dependabot:registry=http://example.com") } + + it { is_expected.to eq("http://example.com") } + + context "when a dependency under a different scope" do + let(:dependency_name) { "@foo/bar" } + + it { is_expected.to eq("https://registry.npmjs.org") } + end + end + + context "with both a scoped npm registry and a global one" do + let(:dependency_name) { "@dependabot/some_dep" } + let(:npmrc_file) do + Dependabot::DependencyFile.new( + name: ".npmrc", + content: "registry=http://example.com\n@dependabot:registry=http://scoped.example.com" + ) + end + + it { is_expected.to eq("http://scoped.example.com") } + + context "when a dependency under a different scope" do + let(:dependency_name) { "@foo/bar" } + + it { is_expected.to eq("http://example.com") } + end + end + end + + describe "registry" do + subject { finder.registry } + + it { is_expected.to eq("registry.npmjs.org") } + + context "with credentials for a private registry" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "https://npm.fury.io/dependabot", + "token" => "secret_token" + } + )] + end + + context "when it doesn't list the dependency" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + end + + it { is_expected.to eq("registry.npmjs.org") } + end + + context "when it lists the dependency" do + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("https://npm.fury.io/dependabot") } + + context "when it returns HTML" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: "Hello!") + end + + it { is_expected.to eq("registry.npmjs.org") } + end + + context "when it doesn't include auth" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot" + } + )] + end + + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("npm.fury.io/dependabot") } + end + end + + context "when it times out" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_raise(Excon::Error::Timeout) + end + + it { is_expected.to eq("registry.npmjs.org") } + end + end + + context "with a space in registry url" do + context "when dependency is in .npmrc file" do + let(:npmrc_file) do + project_dependency_files(project_name).find { |f| f.name == ".npmrc" } + end + let(:project_name) { "nub/npmrc_auth_token_with_space" } + + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot%20with%20space/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("npm.fury.io/dependabot%20with%20space") } + end + end + + context "with a private registry source" do + let(:source) do + { type: "registry", url: "https://npm.fury.io/dependabot" } + end + + it { is_expected.to eq("npm.fury.io/dependabot") } + end + + context "with a git source" do + let(:source) do + { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "v1.0.0" + } + end + + it { is_expected.to eq("registry.npmjs.org") } + end + + context "with credentials that don't have a registry" do + before do + credentials << Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => nil + } + ) + end + + it { is_expected.to eq("registry.npmjs.org") } + end + end + + describe "#auth_headers" do + subject { finder.auth_headers } + + it { is_expected.to eq({}) } + + context "with credentials for a private registry" do + before do + credentials << Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token" + } + ) + end + + context "when it doesn't list the dependency" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + end + + it { is_expected.to eq({}) } + end + + context "when it lists the dependency" do + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("Authorization" => "Bearer secret_token") } + + context "with a username/password style token" do + before do + credentials.last["token"] = "secret:token" + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Basic c2VjcmV0OnRva2Vu" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("Authorization" => "Basic c2VjcmV0OnRva2Vu") } + end + + context "with a token that is in encoded username:password format" do + before do + credentials.last["token"] = Base64.encode64("secret:token") + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .with(headers: { "Authorization" => "Basic c2VjcmV0OnRva2Vu" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq("Authorization" => "Basic c2VjcmV0OnRva2Vu") } + end + + context "without a token" do + before do + credentials.last.delete("token") + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .to_return(status: 404) + stub_request(:get, "https://npm.fury.io/dependabot/etag") + .to_return(status: 200, body: body) + end + + it { is_expected.to eq({}) } + end + end + end + end + + describe "#dependency_url" do + subject(:finder_dependency_url) { finder.dependency_url } + + it { is_expected.to eq("https://registry.npmjs.org/etag") } + + context "with a private registry source" do + let(:source) do + { type: "registry", url: "http://npm.mine.io/dependabot/" } + end + + it { is_expected.to eq("http://npm.mine.io/dependabot/etag") } + end + + context "when multiple js sources are provided" do + let(:dependency_name) { "example" } + let(:requirements) do + [ + { + file: "package.json", + requirement: "^1.0.0", + groups: ["devDependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }, + { + file: "shared-lib/package.json", + requirement: "^1.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.yarnpkg.com" } + } + ] + end + + it "allows multiple sources" do + expect { finder_dependency_url }.not_to raise_error + end + end + + context "when a public registry and a private registry is detected" do + let(:dependency_name) { "example" } + let(:requirements) do + [ + { + file: "package.json", + requirement: "^1.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }, + { + file: "shared-lib/package.json", + requirement: "^1.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.example.org" } + } + ] + end + + it "returns the private registry url" do + expect(finder_dependency_url).to eql("https://registry.example.org/example") + end + end + end +end diff --git a/nub/spec/dependabot/nub/registry_parser_spec.rb b/nub/spec/dependabot/nub/registry_parser_spec.rb new file mode 100644 index 00000000000..d1ca22ee337 --- /dev/null +++ b/nub/spec/dependabot/nub/registry_parser_spec.rb @@ -0,0 +1,136 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/credential" +require "dependabot/nub/registry_parser" + +RSpec.describe Dependabot::Nub::RegistryParser do + subject(:parser) do + described_class.new( + resolved_url: resolved_url, + credentials: credentials + ) + end + + let(:credentials) do + [ + Dependabot::Credential.new( + "type" => "npm_registry", + "registry" => "example.com/victim-npm", + "token" => "victim-token" + ) + ] + end + + # url_for_relevant_cred is invoked when the resolved URL does not match + # the standard tarball format patterns (Gemfury, MyGet/Bintray, Nexus). + # Use metadata-style URLs (without /-/ tarball segment) to test it directly. + + describe "path-segment-aware credential matching via #registry_source_for" do + context "when the resolved URL is within the configured registry path" do + let(:resolved_url) { "https://example.com/victim-npm/my-package" } + + it "returns the configured registry URL" do + result = parser.registry_source_for("my-package") + expect(result).to eq({ type: "registry", url: "https://example.com/victim-npm" }) + end + end + + context "when the resolved URL is under a sibling path that shares a path prefix" do + let(:resolved_url) { "https://example.com/victim-npm-evil/my-package" } + + it "does not attribute the URL to the victim-npm registry" do + result = parser.registry_source_for("my-package") + expect(result[:url]).to eq("https://example.com") + # Must NOT return the credential registry - that would mean credentials leaked + expect(result[:url]).not_to eq("https://example.com/victim-npm") + end + end + + context "when the resolved URL includes an explicit non-default port" do + let(:resolved_url) { "https://example.com:8443/victim-npm/my-package" } + + it "returns a well-formed registry URL and preserves the port" do + result = parser.registry_source_for("my-package") + expect(result[:url]).to eq("https://example.com:8443/victim-npm") + end + end + + context "when the resolved URL is under a completely different path" do + let(:resolved_url) { "https://example.com/other-path/my-package" } + + it "does not attribute the URL to the victim-npm registry" do + result = parser.registry_source_for("my-package") + expect(result[:url]).not_to eq("https://example.com/victim-npm") + end + end + + context "when the resolved URL is on a completely different host" do + let(:resolved_url) { "https://other.example.com/victim-npm/my-package" } + + it "does not attribute the URL to the victim-npm registry" do + result = parser.registry_source_for("my-package") + expect(result[:url]).not_to eq("https://example.com/victim-npm") + end + end + + context "when the registry is a plain hostname with no path restriction" do + let(:credentials) do + [ + Dependabot::Credential.new( + "type" => "npm_registry", + "registry" => "registry.npmjs.org", + "token" => "npmjs-token" + ) + ] + end + let(:resolved_url) { "https://registry.npmjs.org/some-package" } + + it "matches any path on the host" do + result = parser.registry_source_for("some-package") + expect(result[:url]).to eq("https://registry.npmjs.org") + end + end + + context "when the registry URL uses https:// scheme and has a path" do + let(:credentials) do + [ + Dependabot::Credential.new( + "type" => "npm_registry", + "registry" => "https://host.example.com/team-a/npm", + "token" => "team-a-token" + ) + ] + end + + context "when the resolved URL is within the registry path" do + let(:resolved_url) { "https://host.example.com/team-a/npm/my-pkg" } + + it "matches the registry" do + result = parser.registry_source_for("my-pkg") + expect(result[:url]).to eq("https://host.example.com/team-a/npm") + end + end + + context "when the resolved URL shares only a path prefix" do + let(:resolved_url) { "https://host.example.com/team-a-evil/npm/my-pkg" } + + it "does not match the team-a credential" do + result = parser.registry_source_for("my-pkg") + expect(result[:url]).not_to eq("https://host.example.com/team-a/npm") + end + end + + context "when the resolved URL has a different scheme than the credential registry" do + let(:resolved_url) { "http://host.example.com/team-a/npm/my-pkg" } + + it "does not match the https credential and returns a well-formed URL" do + result = parser.registry_source_for("my-pkg") + expect(result[:url]).not_to eq("https://host.example.com/team-a/npm") + expect(result[:url]).not_to include("https://host.example.com/team-a/npm") + end + end + end + end +end diff --git a/nub/spec/dependabot/nub/requirement_spec.rb b/nub/spec/dependabot/nub/requirement_spec.rb new file mode 100644 index 00000000000..f3d318537db --- /dev/null +++ b/nub/spec/dependabot/nub/requirement_spec.rb @@ -0,0 +1,13 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" + +RSpec.describe Dependabot::Nub::Requirement do + it "inherits initialization from Javascript::Requirement" do + requirement = described_class.new("1.0.0") + expect(requirement).to be_a(described_class) + expect(requirement.to_s).to eq("= 1.0.0") + end +end diff --git a/nub/spec/dependabot/nub/update_checker/package_latest_version_finder_spec.rb b/nub/spec/dependabot/nub/update_checker/package_latest_version_finder_spec.rb new file mode 100644 index 00000000000..03789da207f --- /dev/null +++ b/nub/spec/dependabot/nub/update_checker/package_latest_version_finder_spec.rb @@ -0,0 +1,1408 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/nub/update_checker/latest_version_finder" +require "dependabot/credential" +require "dependabot/security_advisory" +require "dependabot/package/release_cooldown_options" +require "dependabot/nub/version" +require "dependabot/nub/package/package_details_fetcher" + +MAX_COOLDOWN_DAYS = 100 * 365 + +RSpec.describe Dependabot::Nub::UpdateChecker::PackageLatestVersionFinder do + let(:registry_base) { "https://registry.npmjs.org" } + let(:version_finder) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions, + security_advisories: security_advisories, + raise_on_ignored: raise_on_ignored, + cooldown_options: cooldown_options + ) + end + + let(:ignored_versions) { [] } + let(:raise_on_ignored) { false } + let(:security_advisories) { [] } + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:dependency_name) { "etag" } + let(:escaped_dependency_name) { dependency_name.gsub("/", "%2F") } + let(:unscoped_dependency_name) { dependency_name.split("/").last } + let(:target_version) { "1.7.0" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: [ + { file: "package.json", requirement: "^1.0.0", groups: [], source: nil } + ], + package_manager: "nub" + ) + end + let(:dependency_version) { "1.0.0" } + let(:registry_listing_url) { "#{registry_base}/#{escaped_dependency_name}" } + let(:registry_response) { fixture("npm_responses", "#{escaped_dependency_name}.json") } + let(:login_form) { fixture("npm_responses", "login_form.html") } + let(:cooldown_options) { nil } + + before do + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: registry_response) + stub_request(:head, "#{registry_base}/#{dependency_name}/-/#{unscoped_dependency_name}-#{target_version}.tgz") + .to_return(status: 200) + end + + describe "#latest_version_from_registry" do + subject(:latest_version_from_registry) { version_finder.latest_version_from_registry } + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + + it "only hits the registry once" do + version_finder.latest_version_from_registry + expect(WebMock).to have_requested(:get, registry_listing_url).once + end + + context "when raise_on_ignored is enabled and later versions are allowed" do + let(:raise_on_ignored) { true } + + it "doesn't raise an error" do + expect { latest_version_from_registry }.not_to raise_error + end + end + + context "when the user is on the latest version" do + let(:dependency_version) { "1.7.0" } + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + + context "when raise_on_ignored is enabled" do + let(:raise_on_ignored) { true } + + it "doesn't raise an error" do + expect { latest_version_from_registry }.not_to raise_error + end + end + end + + context "when the user is ignoring all later versions" do + let(:ignored_versions) { ["> 1.0.0"] } + let(:target_version) { "1.0.0" } + + it { is_expected.to eq(Gem::Version.new("1.0.0")) } + + context "when raise_on_ignored is enabled" do + let(:raise_on_ignored) { true } + + it "raises an error" do + expect { latest_version_from_registry }.to raise_error(Dependabot::AllVersionsIgnored) + end + end + end + + context "when the user is ignoring the latest version" do + let(:ignored_versions) { [">= 1.7.0.a, < 1.8"] } + let(:target_version) { "1.6.0" } + + it { is_expected.to eq(Gem::Version.new("1.6.0")) } + end + + context "when the current version isn't known" do + let(:dependency_version) { nil } + + context "when raise_on_ignored is enabled" do + let(:raise_on_ignored) { true } + + it "doesn't raise an error" do + expect { latest_version_from_registry }.not_to raise_error + end + end + end + + context "when the dependency is a git dependency" do + let(:dependency_version) { "a1b78a929dac93a52f08db4f2847d76d6cfe39bd" } + + context "when raise_on_ignored is enabled" do + let(:raise_on_ignored) { true } + + it "doesn't raise an error" do + expect { latest_version_from_registry }.not_to raise_error + end + end + end + + context "when the user wants a dist tag" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "stable", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:target_version) { "1.5.1" } + + it { is_expected.to eq(Gem::Version.new("1.5.1")) } + end + + context "when the latest version is a prerelease" do + before do + body = fixture("npm_responses", "prerelease.json") + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: body) + stub_request(:get, registry_listing_url + "/2.0.0-rc1") + .to_return(status: 200) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + + context "when the user has specified a bad requirement" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "babel-core@^7.0.0-bridge.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to be_nil } + end + + context "when the user wants a .x version" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.7.0", + requirements: [{ + file: "package.json", + requirement: "1.x", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "when the user is on an old pre-release" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.7.0.beta1", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "when the user is on a pre-release for this version" do + let(:target_version) { "2.0.0-rc1" } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "2.0.0.alpha", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + # NOTE: this is the dist-tag latest version, *not* the latest prerelease + it { is_expected.to eq(Gem::Version.new("2.0.0.pre.rc1")) } + + context "when only says so in their requirements (with a .)" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: requirement, + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:requirement) { "^2.0.0-pre" } + + it { is_expected.to eq(Gem::Version.new("2.0.0.pre.rc1")) } + + context "when specified with a dash" do + let(:requirement) { "^2.0.0-pre" } + + it { is_expected.to eq(Gem::Version.new("2.0.0.pre.rc1")) } + end + end + end + end + + context "when dealing with a private npm-hosted dependency" do + before do + body = fixture("npm_responses", "prerelease.json") + stub_request(:get, "https://registry.npmjs.org/@dependabot%2Fblep") + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://registry.npmjs.org/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + stub_request(:head, "https://registry.npmjs.org/@dependabot/blep/-/blep-1.7.0.tgz") + .to_return(status: 200) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + context "with credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "registry.npmjs.org", + "token" => "secret_token" + } + )] + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "without credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + + before do + stub_request(:get, "https://www.npmjs.com/package/@dependabot/blep") + .to_return(status: 200, body: login_form) + end + + it "raises a Dependabot::PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("registry.npmjs.org") + end + end + end + + context "when the login page is rate limited" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + + before do + stub_request(:get, "https://www.npmjs.com/package/@dependabot/blep") + .to_return(status: 429, body: "") + end + + it "raises a Dependabot::PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("registry.npmjs.org") + end + end + end + + context "with Basic auth credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "registry.npmjs.org", + "token" => "secret:token" + } + )] + end + + before do + body = fixture("npm_responses", "prerelease.json") + stub_request(:get, "https://registry.npmjs.org/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://registry.npmjs.org/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Basic c2VjcmV0OnRva2Vu" }) + .to_return(status: 200, body: body) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + end + + context "when dealing with a dependency hosted on another registry" do + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.1") + .to_return(status: 200) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: { + type: "registry", + url: "https://npm.fury.io/dependabot" + } + }], + package_manager: "nub" + ) + end + + context "when the request times out" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_timeout + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .to_timeout + + # Speed up spec by stopping any sleep logic + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises a to Dependabot::PrivateSourceTimedOut error" do + expect { version_finder.latest_version_from_registry } + .to raise_error(Dependabot::PrivateSourceTimedOut) do |error| + expect(error.source).to eq("npm.fury.io/") + end + end + + context "when dealing with a git dependency" do + before do + allow_any_instance_of(Dependabot::Nub::Package::PackageDetailsFetcher) # rubocop:disable RSpec/AnyInstance + .to receive(:dependency_url) + .and_return("https://npm.fury.io/dependabot/@dependabot%2Fblep") + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: { + type: "git", + url: "https://github.com/unused/repo", + branch: nil, + ref: nil + } + }], + package_manager: "nub" + ) + end + + it { is_expected.to be_nil } + end + end + + context "when the request 500s" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 500) + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .to_return(status: 500) + + # Speed up spec by stopping any sleep logic + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error do |err| + expect(err.class).to eq(Dependabot::DependencyFileNotResolvable) + end + end + end + + context "when the request 200s with a bad body" do + before do + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return( + status: 200, + body: 'user "undefined" is not a member of "KaterTech"' + ) + end + + it "raises a to Dependabot::PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("npm.fury.io/") + end + end + end + + context "with credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + ), Dependabot::Credential.new( + { + "type" => "npm_registry", + "registry" => "npm.fury.io/dependabot", + "token" => "secret_token" + } + )] + end + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + + context "when the latest version has been yanked" do + before do + allow_any_instance_of(Dependabot::Nub::Package::PackageDetailsFetcher) # rubocop:disable RSpec/AnyInstance + .to receive(:dependency_url) + .and_return("https://npm.fury.io/dependabot/@dependabot%2Fblep") + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.1" + ).to_return(status: 404) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot/blep/1.8.1" + ).to_return(status: 404) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/latest" + ).to_return(status: 200) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.0" + ).to_return(status: 200) + end + + it { is_expected.to eq(Dependabot::Nub::Version.new("1.8.0")) } + end + + context "when the registry doesn't implement the /version endpoint" do + before do + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.1" + ).to_return(status: 404) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot/blep/1.8.1" + ).to_return(status: 404) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/latest" + ).to_return(status: 404) + end + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + end + + context "when the registry doesn't escape dependency URLs properly" do + # Looking at you JFrog... + before do + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.1" + ).to_return(status: 404) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot/blep/1.8.1" + ).to_return(status: 200) + stub_request( + :get, + "https://npm.fury.io/dependabot/@dependabot%2Fblep/latest" + ).to_return(status: 200) + end + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + end + + context "without a lockfile" do + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: nil, + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + end + + context "without https" do + before do + body = fixture("gemfury_responses", "gemfury_response_etag.json") + stub_request(:get, "https://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 404) + stub_request(:get, "http://npm.fury.io/dependabot/@dependabot%2Fblep") + .with(headers: { "Authorization" => "Bearer secret_token" }) + .to_return(status: 200, body: body) + stub_request( + :get, "http://npm.fury.io/dependabot/@dependabot%2Fblep/1.8.1" + ).to_return(status: 200) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: { + type: "registry", + url: "http://npm.fury.io/dependabot" + } + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + end + end + + context "without credentials" do + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + + it "raises a to Dependabot::PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("npm.fury.io/") + end + end + + context "with credentials in the .npmrc" do + let(:dependency_files) { project_dependency_files(project_name).select { |f| f.name == ".npmrc" } } + let(:project_name) { "javascript/npmrc_auth_token" } + + it { is_expected.to eq(Gem::Version.new("1.8.1")) } + + context "when it require an environment variable" do + let(:project_name) { "javascript/npmrc_env_auth_token" } + + it "raises a PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("npm.fury.io/") + end + end + end + end + end + end + + context "when the npm link resolves to a redirect" do + let(:redirect_url) { "https://registry.npmjs.org/eTag" } + + before do + stub_request(:get, registry_listing_url) + .to_return(status: 302, headers: { "Location" => redirect_url }) + stub_request(:get, redirect_url) + .to_return( + status: 200, + body: fixture("npm_responses", "etag.json") + ) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "when the npm link resolves to an empty hash" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: "{}") + end + + it { is_expected.to be_nil } + end + + context "when the npm link fails at first" do + before do + body = fixture("npm_responses", "prerelease.json") + stub_request(:get, registry_listing_url) + .to_raise(Excon::Error::Timeout).then + .to_return(status: 200, body: body) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "when the latest version has been yanked" do + before do + body = fixture("npm_responses", "old_latest.json") + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: body) + stub_request(:head, "#{registry_base}/etag/-/etag-1.7.0.tgz") + .to_return(status: 404) + stub_request(:head, "#{registry_base}/etag/-/etag-1.6.0.tgz") + .to_return(status: 200) + end + + it { is_expected.to eq(Gem::Version.new("1.6.0")) } + end + + context "when the npm link resolves to a 403" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 403, body: '{"error":"Forbidden"}') + + # Speed up spec by stopping any sleep logic + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error(Dependabot::RegistryError) + end + end + + context "when the npm link returns 200 but invalid JSON object in body" do + before do + body = fixture("npm_responses", "200_with_invalid_json.json") + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: body) + + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error(Dependabot::DependencyFileNotResolvable) + end + end + + context "when the npm link returns 200 but valid JSON object in body" do + before do + body = fixture("npm_responses", "200_with_valid_json.json") + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: body) + + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .not_to raise_error + end + end + + context "when the npm link resolves to a 404" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 404, body: '{"error":"Not found"}') + + # Speed up spec by stopping any sleep logic + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error do |err| + expect(err.class).to eq(Dependabot::RegistryError) + expect(err.status).to eq(404) + end + end + + context "when dealing with a library dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "does not raise an error" do + expect { version_finder.latest_version_from_registry } + .not_to raise_error + end + end + + context "when dealing with a namespaced dependency" do + before do + stub_request(:get, "https://registry.npmjs.org/@dependabot%2Fblep") + .to_return(status: 404, body: '{"error":"Not found"}') + stub_request(:get, "https://www.npmjs.com/package/@dependabot/blep") + .to_return(status: 200, body: login_form) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot/blep", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "raises a to Dependabot::PrivateSourceAuthenticationFailure error" do + error_class = Dependabot::PrivateSourceAuthenticationFailure + expect { version_finder.latest_version_from_registry } + .to raise_error(error_class) do |error| + expect(error.source).to eq("registry.npmjs.org") + end + end + + context "when it can be found on www.npmjs.com" do + before do + stub_request(:get, "https://www.npmjs.com/package/@dependabot/blep") + .to_return( + status: 200, + body: fixture("npm_responses", "babel-core.html") + ) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error(Dependabot::RegistryError) + end + end + end + end + + context "when the latest version is older than another, non-prerelease" do + before do + body = fixture("npm_responses", "old_latest.json") + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: body) + stub_request(:head, "#{registry_base}/etag/-/etag-1.6.0.tgz") + .to_return(status: 200) + stub_request(:head, "#{registry_base}/etag/-/etag-1.6.3.tgz") + .to_return(status: 200) + end + + it { is_expected.to eq(Gem::Version.new("1.6.0")) } + + context "when the user is already using" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.7.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + + context "when the user has pinned in their package.json" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: "^1.7.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + end + + context "when the npm registry package lookup returns a 404 error" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 404, body: '{"error":"Not found"}') + + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error do |err| + expect(err.class).to eq(Dependabot::RegistryError) + expect(err.status).to eq(404) + end + end + end + + context "when the dependency has been yanked" do + before do + stub_request(:head, "#{registry_base}/etag/-/etag-1.6.0.tgz") + .to_return(status: 200) + stub_request(:head, "#{registry_base}/etag/-/etag-1.6.3.tgz") + .to_return(status: 200) + stub_request(:head, "#{registry_base}/etag/-/etag-1.7.0.tgz") + .to_return(status: 404) + end + + let(:registry_response) do + fixture("npm_responses", "etag_yanked.json") + end + + it "picks the latest non-yanked dist-tags version" do + expect(latest_version_from_registry).to eq(Gem::Version.new("1.6.3")) + end + end + + context "when the npm registry package lookup returns a 500 error" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 500, body: '{"error":"Not found"}') + + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error do |err| + expect(err.class).to eq(Dependabot::DependencyFileNotResolvable) + end + end + end + + context "when the npm registry uri is invalid and lookup returns a bad URI error" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 500, body: '{"error":"bad URI(is not URI?): "https://registry.npmjs.org/\"/webpack""}') + + allow(version_finder).to receive(:sleep).and_return(true) + end + + it "raises an error" do + expect { version_finder.latest_version_from_registry } + .to raise_error do |err| + expect(err.class).to eq(Dependabot::DependencyFileNotResolvable) + end + end + end + + context "when cooldown is applied to dist tag version" do + let(:cooldown_options) do + Dependabot::Package::ReleaseCooldownOptions.new( + default_days: MAX_COOLDOWN_DAYS + ) + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "stable", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:target_version) { "1.5.1" } + + it { is_expected.to be_nil } + end + end + + describe "#latest_version_with_no_unlock" do + subject { version_finder.latest_version_with_no_unlock } + + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: requirements, + package_manager: "nub" + ) + end + let(:requirements) do + [{ + file: "package.json", + requirement: req_string, + groups: [], + source: nil + }] + end + let(:req_string) { "^1.0.0" } + + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + + context "when a dist tag is specified" do + let(:req_string) { "stable" } + let(:target_version) { "1.5.1" } + + it { is_expected.to eq(Gem::Version.new("1.5.1")) } + + context "when it can't be found" do + let(:target_version) { "1.7.0" } + let(:req_string) { "unknown" } + + # If the dist tag can't be found then we use the `latest` dist tag + it { is_expected.to eq(Gem::Version.new("1.7.0")) } + end + end + + context "when a version with a v-prefix is specified" do + let(:req_string) { "v1.0.0" } + let(:target_version) { "1.0.0" } + + it { is_expected.to eq(Gem::Version.new("1.0.0")) } + end + + context "when constrained" do + let(:req_string) { "<= 1.5.0" } + let(:target_version) { "1.5.0" } + + it { is_expected.to eq(Gem::Version.new("1.5.0")) } + + context "when dealing with multiple requirements" do + let(:requirements) do + [{ + file: "package.json", + requirement: "<= 1.5.0", + groups: [], + source: nil + }, { + file: "package2.json", + requirement: "^1.5.0", + groups: [], + source: nil + }] + end + + it { is_expected.to eq(Gem::Version.new("1.5.0")) } + end + end + + context "when the dependency has been deprecated" do + let(:registry_response) do + fixture("npm_responses", "etag_deprecated.json") + end + + it { is_expected.to be_nil } + end + end + + describe "#lowest_security_fix_version" do + subject(:lowest_security_fix_version) { version_finder.lowest_security_fix_version } + + let(:target_version) { "1.2.1" } + + let(:dependency_version) { "1.1.0" } + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "rails", + package_manager: "nub", + vulnerable_versions: ["~1.1.0", "1.2.0", "1.3.0"] + ) + ] + end + + it { is_expected.to eq(Gem::Version.new("1.2.1")) } + + context "when the lowest version has been yanked" do + before do + stub_request(:head, "#{registry_base}/etag/-/etag-1.2.1.tgz") + .to_return(status: 404) + stub_request(:head, "#{registry_base}/etag/-/etag-1.3.1.tgz") + .to_return(status: 200) + end + + it { is_expected.to eq(Gem::Version.new("1.3.1")) } + end + + context "when the user wants a dist tag" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "stable", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:target_version) { "1.5.1" } + + it { is_expected.to eq(Gem::Version.new("1.5.1")) } + end + + context "when the user has ignored all versions" do + let(:ignored_versions) { [">= 0, < 99"] } + + it { is_expected.to be_nil } + + context "with raise_on_ignored" do + let(:raise_on_ignored) { true } + + it "raises exception" do + expect { lowest_security_fix_version }.to raise_error(Dependabot::AllVersionsIgnored) + end + end + end + + context "when the user has ignored all but vulnerable versions" do + # 1.1.0 is not ignored, but it is vulnerable + let(:ignored_versions) { ["> 0, < 1.1.0", "> 1.2.0, < 99"] } + + it { is_expected.to be_nil } + + context "with raise_on_ignored" do + let(:raise_on_ignored) { true } + + it "raises exception" do + expect { lowest_security_fix_version }.to raise_error(Dependabot::AllVersionsIgnored) + end + end + end + end + + describe "#possible_versions" do + subject(:possible_versions) { version_finder.possible_versions } + + it "returns a list of versions" do + expect(possible_versions).to eq( + [ + Dependabot::Nub::Version.new("1.7.0"), + Dependabot::Nub::Version.new("1.6.0"), + Dependabot::Nub::Version.new("1.5.1"), + Dependabot::Nub::Version.new("1.5.0"), + Dependabot::Nub::Version.new("1.4.0"), + Dependabot::Nub::Version.new("1.3.1"), + Dependabot::Nub::Version.new("1.3.0"), + Dependabot::Nub::Version.new("1.2.1"), + Dependabot::Nub::Version.new("1.2.0"), + Dependabot::Nub::Version.new("1.1.0"), + Dependabot::Nub::Version.new("1.0.1"), + Dependabot::Nub::Version.new("1.0.0") + ] + ) + end + + context "when some versions are being ignored" do + let(:ignored_versions) { [">= 1.1.0, < 1.6"] } + + it "excludes the ignored versions" do + expect(possible_versions).to eq( + [ + Dependabot::Nub::Version.new("1.7.0"), + Dependabot::Nub::Version.new("1.6.0"), + Dependabot::Nub::Version.new("1.0.1"), + Dependabot::Nub::Version.new("1.0.0") + ] + ) + end + end + + context "when the dependency has been deprecated" do + let(:registry_response) do + fixture("npm_responses", "etag_deprecated.json") + end + + it { is_expected.to eq([]) } + end + end + + describe "#possible_versions_with_details" do + subject(:possible_versions_with_details) do + version_finder.possible_versions_with_details + end + + context "with versions that would be considered equivalent" do + let(:registry_listing_url) do + "https://registry.npmjs.org/react-test-renderer" + end + let(:registry_response) do + fixture("npm_responses", "react-test-renderer.json") + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "react-test-renderer", + version: "16.0.0-beta.5", + requirements: [{ + file: "package.json", + requirement: "16.0.0-beta.5", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "returns a list of versions" do + expect(possible_versions_with_details.count).to eq(49) + end + end + + context "with ignored versions" do + let(:registry_listing_url) { "https://registry.npmjs.org/react" } + let(:registry_response) do + fixture("npm_responses", "react.json") + end + let(:ignored_versions) { ["<15.0.0", "^16.0.0"] } + + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: "15.3.0", + requirements: [{ + file: "package.json", + requirement: "^15.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "excludes ignored versions" do + versions = possible_versions_with_details + latest_version = versions.first.first + expect(versions.count).to eq(20) + expect(latest_version) + .to eq(Dependabot::Nub::Version.new("15.6.2")) + end + end + + context "with only deprecated versions" do + let(:registry_response) do + fixture("npm_responses", "etag_deprecated.json") + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.1.0", + requirements: [{ + file: "package.json", + requirement: "1.1.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "returns no versions" do + expect(possible_versions_with_details).to eq([]) + end + end + end + + describe "#possible_previous_versions_with_details" do + subject(:possible_previous_versions_with_details) do + version_finder.possible_previous_versions_with_details + end + + context "with ignored versions and non pre-release version requirement" do + let(:registry_listing_url) { "https://registry.npmjs.org/react" } + let(:registry_response) do + fixture("npm_responses", "react.json") + end + let(:ignored_versions) { ["<15.0.0", "^16.0.0"] } + + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: "15.6.2", + requirements: [{ + file: "package.json", + requirement: "^15.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "includes ignored versions and excludes pre-releases" do + versions = possible_previous_versions_with_details + latest_version = versions.first.first + expect(versions.count).to eq(80) + expect(latest_version) + .to eq(Dependabot::Nub::Version.new("16.6.0")) + end + end + + context "with pre-release version requirement" do + let(:registry_listing_url) { "https://registry.npmjs.org/react" } + let(:registry_response) do + fixture("npm_responses", "react.json") + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: "15.6.0-rc.1", + requirements: [{ + file: "package.json", + requirement: "^15.6.0-rc.1", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "includes pre-released versions" do + versions = possible_previous_versions_with_details + latest_version = versions.first.first + expect(versions.count).to eq(103) + expect(latest_version) + .to eq(Dependabot::Nub::Version.new("16.6.0")) + end + end + + context "with only deprecated versions" do + let(:registry_response) do + fixture("npm_responses", "etag_deprecated.json") + end + + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.1.0", + requirements: [{ + file: "package.json", + requirement: "1.1.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "returns all versions" do + expect(possible_previous_versions_with_details.count).to eq(13) + end + end + end +end diff --git a/nub/spec/dependabot/nub/update_checker/subdependency_version_resolver_spec.rb b/nub/spec/dependabot/nub/update_checker/subdependency_version_resolver_spec.rb new file mode 100644 index 00000000000..10a968e09e8 --- /dev/null +++ b/nub/spec/dependabot/nub/update_checker/subdependency_version_resolver_spec.rb @@ -0,0 +1,65 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub/update_checker/subdependency_version_resolver" + +RSpec.describe Dependabot::Nub::UpdateChecker::SubdependencyVersionResolver do + subject(:latest_resolvable_version) { resolver.latest_resolvable_version } + + let(:dependency) do + Dependabot::Dependency.new( + name: "@dependabot-fixtures/npm-transitive-dependency", + version: "1.0.0", + requirements: [], + package_manager: "nub" + ) + end + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com" + } + )] + end + let(:dependency_files) do + [Dependabot::DependencyFile.new(name: "nub.lock", content: "{}", directory: ".")] + end + let(:latest_allowable_version) { Dependabot::Nub::Version.new("1.0.1") } + let(:resolver) do + described_class.new( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: [], + latest_allowable_version: latest_allowable_version, + repo_contents_path: nil + ) + end + let(:dependency_files_builder) do + instance_double(Dependabot::Nub::UpdateChecker::DependencyFilesBuilder) + end + + before do + allow(resolver).to receive_messages( + dependency_files_builder: dependency_files_builder, + filtered_lockfiles: dependency_files, + version_from_updated_lockfiles: Gem::Version.new("1.0.1") + ) + allow(dependency_files_builder).to receive(:write_temporary_dependency_files) do + File.write("nub.lock", "dummy lockfile") + end + + allow(Dependabot::Nub::Helpers).to receive(:run_nub_command) + end + + it "runs nub update with --ignore-scripts for subdependency lockfile updates" do + expect(latest_resolvable_version).to eq(Gem::Version.new("1.0.1")) + + expect(Dependabot::Nub::Helpers).to have_received(:run_nub_command).with( + "update @dependabot-fixtures/npm-transitive-dependency --lockfile-only --ignore-scripts", + fingerprint: "update --lockfile-only --ignore-scripts" + ) + end +end diff --git a/nub/spec/dependabot/nub/update_checker/version_resolver_spec.rb b/nub/spec/dependabot/nub/update_checker/version_resolver_spec.rb new file mode 100644 index 00000000000..04cd549da2f --- /dev/null +++ b/nub/spec/dependabot/nub/update_checker/version_resolver_spec.rb @@ -0,0 +1,564 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/dependency" +require "dependabot/dependency_file" +require "dependabot/nub/update_checker/version_resolver" + +RSpec.describe Dependabot::Nub::UpdateChecker::VersionResolver do + let(:resolver) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + latest_allowable_version: latest_allowable_version, + latest_version_finder: latest_version_finder, + repo_contents_path: repo_contents_path, + dependency_group: group + ) + end + let(:tmp_path) { Dependabot::Utils::BUMP_TMP_DIR_PATH } + let(:dependency_files) { project_dependency_files(project_name) } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:repo_contents_path) { build_tmp_repo(project_name, path: "projects") } + let(:group) { nil } + let(:latest_version_finder) do + Dependabot::Nub::UpdateChecker::PackageLatestVersionFinder.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: [], + security_advisories: [] + ) + end + let(:react_dom_registry_listing_url) do + "https://registry.npmjs.org/react-dom" + end + let(:react_dom_registry_response) do + fixture("npm_responses", "react-dom.json") + end + let(:react_registry_listing_url) { "https://registry.npmjs.org/react" } + let(:react_registry_response) do + fixture("npm_responses", "react.json") + end + let(:opentelemetry_api_registry_listing_url) { "https://registry.npmjs.org/%40opentelemetry%2Fapi" } + let(:opentelemetry_api_registry_response) do + fixture("npm_responses", "opentelemetry-api.json") + end + let(:opentelemetry_context_async_hooks_registry_listing_url) do + "https://registry.npmjs.org/%40opentelemetry%2Fcontext-async-hooks" + end + let(:opentelemetry_context_async_hooks_registry_response) do + fixture("npm_responses", "opentelemetry-context-async-hooks.json") + end + + before do + stub_request(:get, react_dom_registry_listing_url) + .to_return(status: 200, body: react_dom_registry_response) + stub_request(:get, react_dom_registry_listing_url + "/latest") + .to_return(status: 200, body: "{}") + stub_request(:get, react_registry_listing_url) + .to_return(status: 200, body: react_registry_response) + stub_request(:get, react_registry_listing_url + "/latest") + .to_return(status: 200, body: "{}") + stub_request(:get, opentelemetry_api_registry_listing_url) + .to_return(status: 200, body: opentelemetry_api_registry_response) + stub_request(:get, opentelemetry_context_async_hooks_registry_listing_url) + .to_return(status: 200, body: opentelemetry_context_async_hooks_registry_response) + end + + after do + Dependabot::Experiments.reset! + end + + describe "#latest_resolvable_version" do + subject(:latest_resolvable_version) { resolver.latest_resolvable_version } + + context "with no lockfile" do + context "when updating a tightly coupled monorepo dependency" do + let(:project_name) { "javascript/peer_dependency_no_lockfile" } + let(:latest_allowable_version) { Gem::Version.new("2.5.21") } + let(:dependency) do + Dependabot::Dependency.new( + name: "vue", + version: nil, + requirements: [{ + file: "package.json", + requirement: "2.5.20", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }], + package_manager: "nub" + ) + end + + context "with other parts of the monorepo present" do + let(:project_name) { "javascript/monorepo_dep_multiple_no_lockfile" } + + it { is_expected.to be_nil } + end + + context "without other parts of the monorepo" do + let(:project_name) { "javascript/monorepo_dep_single_no_lockfile" } + + it { is_expected.to eq(latest_allowable_version) } + end + end + + context "when updating a dependency without peer dependency issues" do + let(:project_name) { "javascript/peer_dependency_no_lockfile" } + let(:latest_allowable_version) { Gem::Version.new("1.0.0") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(latest_allowable_version) } + + context "when requirement is a git dependency" do + let(:project_name) { "javascript/git_dependency_no_lockfile" } + let(:latest_allowable_version) do + "0c6b15a88bc10cd47f67a09506399dfc9ddc075d" + end + let(:dependency) do + Dependabot::Dependency.new( + name: "is-number", + version: nil, + requirements: [{ + requirement: nil, + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + } + }], + package_manager: "nub" + ) + end + + it { is_expected.to eq(latest_allowable_version) } + end + end + + context "when there are already peer requirement issues" do + let(:project_name) { "javascript/peer_dependency_mismatch_no_lockfile" } + + context "when dealing with a dependency with issues" do + let(:latest_allowable_version) { Gem::Version.new("16.3.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^15.2.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + it { is_expected.to eq(Gem::Version.new("16.3.1")) } + end + + context "when updating an unrelated dependency" do + let(:latest_allowable_version) { Gem::Version.new("0.2.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "fetch-factory", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^0.0.1", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + it { is_expected.to eq(Gem::Version.new("0.2.1")) } + + context "with a dependency version that can't be found" do + let(:project_name) { "javascript/yanked_version_no_lockfile" } + let(:latest_allowable_version) { Gem::Version.new("99.0.0") } + let(:dependency) do + Dependabot::Dependency.new( + name: "fetch-factory", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^99.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + # We let the latest version through here, rather than raising. + # Eventually error handling should be moved from the FileUpdater + # to here + it { is_expected.to eq(Gem::Version.new("99.0.0")) } + end + end + end + end + end + + describe "#dependency_updates_from_full_unlock" do + subject { resolver.dependency_updates_from_full_unlock } + + describe "#dependency_updates_from_full_unlock resolves previous version" do + subject do + resolver.dependency_updates_from_full_unlock.first[:previous_version] + end + + let(:project_name) { "javascript/exact_version_requirements_no_lockfile" } + + let(:latest_allowable_version) { Gem::Version.new("1.1.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "chalk", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "0.3.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/chalk" + end + let(:response) do + fixture("npm_responses", "chalk.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("0.3.0") } + end + + describe "#latest_resolvable_previous_version" do + subject(:lrv) do + resolver.latest_resolvable_previous_version(latest_allowable_version) + end + + let(:project_name) { "javascript/exact_version_requirements_no_lockfile" } + + describe "when version requirement is exact" do + let(:latest_allowable_version) { Gem::Version.new("1.1.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "chalk", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "0.3.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/chalk" + end + let(:response) do + fixture("npm_responses", "chalk.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("0.3.0") } + end + + describe "when version requirement is missing a patch" do + let(:latest_allowable_version) { Gem::Version.new("15.6.2") } + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "15.3", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/react" + end + let(:response) do + fixture("npm_responses", "react.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("15.3.2") } + end + + describe "with multiple version requirements" do + let(:latest_allowable_version) { Gem::Version.new("15.6.2") } + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^15.4.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }, { + file: "other/package.json", + requirement: "< 15.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/react" + end + let(:response) do + fixture("npm_responses", "react.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it "picks the lowest requirements max version" do + expect(lrv).to eq("0.14.9") + end + end + + describe "when version requirement has a caret" do + let(:latest_allowable_version) { Gem::Version.new("1.8.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^1.1.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/etag" + end + let(:response) do + fixture("npm_responses", "etag.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("1.7.0") } + end + + describe "when all versions are deprecated" do + let(:latest_allowable_version) { Gem::Version.new("1.8.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^1.1.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/etag" + end + let(:response) do + fixture("npm_responses", "etag_deprecated.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("1.7.0") } + end + + describe "when current version requirement is deprecated" do + let(:latest_allowable_version) { Gem::Version.new("15.6.2") } + let(:dependency) do + Dependabot::Dependency.new( + name: "react", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^0.7.1", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/react" + end + let(:response) do + fixture("npm_responses", "react.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to eq("0.7.1") } + end + + context "when the resolved previous version is the same as the updated" do + let(:latest_allowable_version) { Gem::Version.new("0.3.0") } + let(:dependency) do + Dependabot::Dependency.new( + name: "chalk", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "0.3.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + let(:listing_url) do + "https://registry.npmjs.org/chalk" + end + let(:response) do + fixture("npm_responses", "chalk.json") + end + + before do + stub_request(:get, listing_url) + .to_return(status: 200, body: response) + stub_request(:get, listing_url + "/latest") + .to_return(status: 200, body: "{}") + end + + it { is_expected.to be_nil } + + context "when the updated version is a string" do + let(:latest_allowable_version) { "0.3.0" } + + it { is_expected.to be_nil } + end + end + + context "when the dependency has a previous version" do + let(:latest_allowable_version) { Gem::Version.new("1.1.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "chalk", + version: "0.2.0", + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^0.2.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + it { is_expected.to eq("0.2.0") } + end + + context "when the previous version is a git sha" do + let(:latest_allowable_version) { Gem::Version.new("1.1.1") } + let(:dependency) do + Dependabot::Dependency.new( + name: "chalk", + version: "9ec4acec6abd23f9b23e33b1171e50d41953f00d", + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: nil, + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }] + ) + end + + it { is_expected.to eq("9ec4acec6abd23f9b23e33b1171e50d41953f00d") } + end + end + end +end diff --git a/nub/spec/dependabot/nub/update_checker_spec.rb b/nub/spec/dependabot/nub/update_checker_spec.rb new file mode 100644 index 00000000000..3600dae67c9 --- /dev/null +++ b/nub/spec/dependabot/nub/update_checker_spec.rb @@ -0,0 +1,1342 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" + +require "dependabot/dependency_file" +require "dependabot/dependency" +require "dependabot/nub/metadata_finder" +require "dependabot/nub/update_checker" +require "dependabot/requirements_update_strategy" +require_common_spec "update_checkers/shared_examples_for_update_checkers" + +RSpec.describe Dependabot::Nub::UpdateChecker do + let(:dependency_version) { "1.0.0" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: dependency_version, + requirements: [ + { file: "package.json", requirement: "^1.0.0", groups: [], source: nil } + ], + package_manager: "nub" + ) + end + let(:target_version) { "1.7.0" } + let(:unscoped_dependency_name) { dependency_name.split("/").last } + let(:escaped_dependency_name) { dependency_name.gsub("/", "%2F") } + let(:dependency_name) { "etag" } + let(:credentials) do + [Dependabot::Credential.new( + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => "token" + } + )] + end + let(:options) { {} } + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + let(:requirements_update_strategy) { nil } + let(:security_advisories) { [] } + let(:ignored_versions) { [] } + let(:update_cooldown) { nil } + let(:checker) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions, + security_advisories: security_advisories, + requirements_update_strategy: requirements_update_strategy, + update_cooldown: update_cooldown, + options: options + ) + end + let(:registry_response) do + fixture("npm_responses", "#{escaped_dependency_name}.json") + end + let(:registry_listing_url) { "#{registry_base}/#{escaped_dependency_name}" } + let(:registry_base) { "https://registry.npmjs.org" } + + before do + stub_request(:get, registry_listing_url) + .to_return(status: 200, body: registry_response) + stub_request(:head, "#{registry_base}/#{dependency_name}/-/#{unscoped_dependency_name}-#{target_version}.tgz") + .to_return(status: 200) + end + + after do + Dependabot::Experiments.reset! + end + + it_behaves_like "an update checker" + + describe "#vulnerable?" do + context "when the dependency has multiple versions" do + let(:dependency) do + Dependabot::Dependency.new( + name: "foo", + version: "1.0.0", + requirements: (foo_v1.requirements + foo_v2.requirements).uniq, + package_manager: "nub", + metadata: { all_versions: [foo_v1, foo_v2] } + ) + end + + let(:foo_v1) do + Dependabot::Dependency.new( + name: "foo", + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: nil, + source: nil + }], + package_manager: "nub" + ) + end + + let(:foo_v2) do + Dependabot::Dependency.new( + name: "foo", + version: "2.0.0", + requirements: [{ + file: "nub.lock", + requirement: "^2.0.0", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + }], + package_manager: "nub" + ) + end + + context "when any of the versions is vulnerable" do + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "foo", + package_manager: "nub", + vulnerable_versions: [">=2.0.0 <2.0.3"], + safe_versions: [">=1.0.0 <2.0.0", ">=2.0.3"] + ) + ] + end + + it "returns true" do + expect(checker.vulnerable?).to be(true) + end + end + + context "when none of the versions is vulnerable" do + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "foo", + package_manager: "nub", + vulnerable_versions: ["<1.0.0"], + safe_versions: [">=1.0.0"] + ) + ] + end + + it "returns false" do + expect(checker.vulnerable?).to be(false) + end + end + end + end + + describe "#up_to_date?" do + context "with no lockfile" do + let(:dependency_files) { project_dependency_files("javascript/packages_name_outdated_no_lockfile") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + requirement: "^1.0.0", + file: "package.json", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it "returns false when there is a newer version available" do + expect(checker).not_to be_up_to_date + end + end + + context "with a latest version requirement" do + let(:dependency_files) { project_dependency_files("javascript/latest_requirement") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [ + { file: "package.json", requirement: "latest", groups: [], source: nil } + ], + package_manager: "nub" + ) + end + + it "is up to date because there's nothing to update" do + expect(checker).to be_up_to_date + end + end + end + + describe "#can_update?" do + subject(:can_update) { checker.can_update?(requirements_to_unlock: :own) } + + context "when the dependency is outdated" do + it { is_expected.to be_truthy } + + context "with no version" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: "^0.9.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to be_truthy } + end + end + + context "when the dependency is up-to-date" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.7.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + it { is_expected.to be_falsey } + + context "with no version" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: nil, + requirements: [{ + file: "package.json", + requirement: requirement, + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + + context "when a requirement that exactly matches" do + let(:requirement) { "^1.7.0" } + + it { is_expected.to be_falsey } + end + + context "when a requirement that covers and doesn't exactly match" do + let(:requirement) { "^1.6.0" } + + it { is_expected.to be_falsey } + end + end + end + + context "when dealing with a scoped package name" do + let(:dependency_name) { "@dependabot-fixtures/npm-parent-dependency" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:target_version) { "2.0.2" } + + before do + allow_any_instance_of(described_class::VersionResolver) + .to receive(:latest_resolvable_version) + .and_return(Dependabot::Nub::Version.new("1.7.0")) + end + + it { is_expected.to be_truthy } + end + end + + describe "#latest_version" do + subject(:latest_version) { checker.latest_version } + + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + + it "delegates to PackageLatestVersionFinder" do + expect(described_class::PackageLatestVersionFinder).to receive(:new).with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + raise_on_ignored: false, + security_advisories: security_advisories, + cooldown_options: nil + ).and_call_original + + expect(checker.latest_version).to eq(Dependabot::Nub::Version.new("1.7.0")) + end + + it "only hits the registry once" do + checker.latest_version + expect(WebMock).to have_requested(:get, registry_listing_url).once + end + + context "with multiple requirements" do + let(:dependency) do + Dependabot::Dependency.new( + name: "preact", + version: "0.1.0", + package_manager: "nub", + requirements: [ + { + requirement: "^0.1.0", + file: "nub.lock", + groups: ["dependencies"], + source: { type: "registry", url: "https://registry.npmjs.org" } + } + ] + ) + end + + before do + stub_request(:get, "https://registry.npmjs.org/preact") + .and_return(status: 200, body: JSON.pretty_generate({})) + end + + specify { expect { latest_version }.not_to raise_error } + end + + context "with a git dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "is-number", + version: current_version, + requirements: [{ + requirement: req, + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: ref + } + }], + package_manager: "nub" + ) + end + let(:upload_pack_fixture) { "is-number" } + let(:commit_compare_response) do + fixture("github", "commit_compare_diverged.json") + end + let(:registry_listing_url) { "https://registry.npmjs.org/is-number" } + let(:registry_response) do + fixture("npm_responses", "is_number.json") + end + let(:current_version) { "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8" } + + before do + git_url = "https://github.com/jonschlinkert/is-number.git" + git_header = { + "content-type" => "application/x-git-upload-pack-advertisement" + } + stub_request(:get, git_url + "/info/refs?service=git-upload-pack") + .with(basic_auth: %w(x-access-token token)) + .to_return( + status: 200, + body: fixture("git", "upload_packs", upload_pack_fixture), + headers: git_header + ) + stub_request(:get, registry_listing_url + "/4.0.0") + .to_return(status: 200) + + repo_url = "https://api.github.com/repos/jonschlinkert/is-number" + stub_request(:get, repo_url + "/compare/4.0.0...#{ref}") + .to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + end + + context "with a branch" do + let(:ref) { "master" } + let(:req) { nil } + + it "fetches the latest SHA-1 hash of the head of the branch" do + expect(checker.latest_version) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + + context "when ref doesn't exist" do + let(:ref) { "nonexistent" } + let(:req) { nil } + + it "fetches the latest SHA-1 hash of the head of the branch" do + expect(checker.latest_version).to eq(current_version) + end + end + + context "when dealing with a dependency that doesn't have a release" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 404, body: "{}") + end + + it "fetches the latest SHA-1 hash of the head of the branch" do + expect(checker.latest_version) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + end + + context "when a dependency returns 405 status" do + before do + stub_request(:get, registry_listing_url) + .to_return(status: 405, body: "{}") + end + + it "fetches the latest SHA-1 hash of the head of the branch" do + expect(checker.latest_version) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + end + end + + context "with a commit ref" do + let(:ref) { "d5ac058" } + let(:req) { nil } + + it "returns the current version" do + expect(checker.latest_version).to eq(current_version) + end + end + + context "with a ref that looks like a version" do + let(:ref) { "2.0.0" } + let(:req) { nil } + + it "fetches the latest SHA-1 hash of the latest version tag" do + expect(checker.latest_version) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + + context "when there are no tags" do + let(:upload_pack_fixture) { "no_tags" } + + it { is_expected.to be_nil } + end + + context "with a cooldown period configured" do + let(:update_cooldown) do + Dependabot::Package::ReleaseCooldownOptions.new(default_days: 90) + end + + before do + allow(checker.send(:git_commit_checker)) + .to receive(:refs_for_tag_with_detail) + .and_return( + [ + Dependabot::GitTagWithDetail.new(tag: "3.0.0", release_date: "2018-01-02"), + Dependabot::GitTagWithDetail.new( + tag: "4.0.0", + release_date: Time.now.strftime("%Y-%m-%d") + ) + ] + ) + end + + it "skips the version tag still within its cooldown window" do + expect(checker.latest_version) + .to eq("af885e2e890b9ef0875edd2b117305119ee5bdc5") + end + + context "when there is no cooldown (e.g. a security update)" do + let(:update_cooldown) { nil } + + it "uses the latest version tag" do + expect(checker.latest_version) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + end + end + end + + context "with a requirement" do + let(:ref) { "master" } + let(:req) { "^2.0.0" } + let(:current_version) { "2.0.2" } + + it "fetches the latest version tag" do + expect(checker.latest_version).to eq(Dependabot::Nub::Version.new("4.0.0")) + end + + context "when there are no tags" do + let(:upload_pack_fixture) { "no_tags" } + + it { is_expected.to be_nil } + end + end + end + end + + describe "#lowest_security_fix_version" do + subject(:lowest_security_fix) { checker.lowest_security_fix_version } + + let(:target_version) { "1.0.1" } + + it "finds the lowest available non-vulnerable version" do + expect(checker.lowest_security_fix_version) + .to eq(Dependabot::Nub::Version.new("1.0.1")) + end + + context "with a security vulnerability" do + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: dependency_name, + package_manager: "nub", + vulnerable_versions: ["<= 1.2.0"] + ) + ] + end + + let(:target_version) { "1.2.1" } + + it "finds the lowest available non-vulnerable version" do + expect(lowest_security_fix).to eq(Dependabot::Nub::Version.new("1.2.1")) + end + end + + context "when the VulnerabilityAudit finds multiple top-level ancestors" do + let(:vulnerability_auditor) do + instance_double(described_class::VulnerabilityAuditor) + end + + before do + allow(described_class::VulnerabilityAuditor).to receive(:new).and_return(vulnerability_auditor) + allow(vulnerability_auditor).to receive(:audit).and_return( + { + "fix_available" => true, + "top_level_ancestors" => %w(applause lodash) + } + ) + end + + it "returns nil to force a full unlock" do + expect(lowest_security_fix).to be_nil + end + end + end + + describe "#latest_resolvable_version" do + subject { checker.latest_resolvable_version } + + it { is_expected.to eq(Dependabot::Nub::Version.new("1.7.0")) } + + context "when dealing with a sub-dependency" do + let(:dependency_name) { "@dependabot-fixtures/npm-transitive-dependency" } + let(:target_version) { "1.0.1" } + + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [], + package_manager: "nub" + ) + end + + it "delegates to SubdependencyVersionResolver" do + dummy_version_resolver = + instance_double(described_class::SubdependencyVersionResolver) + + expect(described_class::SubdependencyVersionResolver) + .to receive(:new) + .with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + latest_allowable_version: Dependabot::Nub::Version.new("1.0.1"), + repo_contents_path: nil + ).and_return(dummy_version_resolver) + expect(dummy_version_resolver) + .to receive(:latest_resolvable_version) + .and_return(Dependabot::Nub::Version.new("1.0.0")) + + expect(checker.latest_resolvable_version) + .to eq(Dependabot::Nub::Version.new("1.0.0")) + end + end + end + + describe "#preferred_resolvable_version" do + subject { checker.preferred_resolvable_version } + + it { is_expected.to eq(Dependabot::Nub::Version.new("1.7.0")) } + + context "with a security vulnerability" do + let(:dependency_version) { "1.1.0" } + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "rails", + package_manager: "nub", + vulnerable_versions: ["~1.1.0", "1.2.0", "1.3.0"] + ) + ] + end + let(:target_version) { "1.2.1" } + + it { is_expected.to eq(Dependabot::Nub::Version.new("1.2.1")) } + + context "when dealing with a sub-dependency" do + let(:dependency_name) { "@dependabot-fixtures/npm-transitive-dependency" } + let(:target_version) { "1.0.1" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [], + package_manager: "nub" + ) + end + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "rails", + package_manager: "nub", + vulnerable_versions: ["<= 1.0.0"] + ) + ] + end + + it "delegates to SubdependencyVersionResolver" do + dummy_version_resolver = + instance_double(described_class::SubdependencyVersionResolver) + + expect(described_class::SubdependencyVersionResolver) + .to receive(:new) + .with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + latest_allowable_version: Dependabot::Nub::Version.new("1.0.1"), + repo_contents_path: nil + ).and_return(dummy_version_resolver) + expect(dummy_version_resolver) + .to receive(:latest_resolvable_version) + .and_return(Dependabot::Nub::Version.new("1.0.1")) + + expect(checker.preferred_resolvable_version) + .to eq(Dependabot::Nub::Version.new("1.0.1")) + end + end + end + end + + describe "#lowest_resolvable_security_fix_version" do + subject(:lowest_resolvable_security_fix_version) { checker.lowest_resolvable_security_fix_version } + + let(:dependency_files) { project_dependency_files("javascript/locked_transitive_dependency") } + let(:dependency_name) { "@dependabot-fixtures/npm-transitive-dependency" } + let(:target_version) { "1.2.1" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [], + package_manager: "nub" + ) + end + + context "when the dependency is not vulnerable" do + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: dependency_name, + package_manager: "nub", + vulnerable_versions: ["<1.0.0"], + safe_versions: [">=1.0.0 <2.0.0"] + ) + ] + end + + it "raises an error" do + expect { lowest_resolvable_security_fix_version }.to raise_error("Dependency not vulnerable!") + end + end + + context "when the dependency is vulnerable" do + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: dependency_name, + package_manager: "nub", + vulnerable_versions: ["<1.2.1"], + safe_versions: [">=1.2.1 <2.0.0"] + ) + ] + end + + context "when the dependency is top-level" do + let(:dependency_name) { "@dependabot-fixtures/npm-parent-dependency" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }], + package_manager: "nub" + ) + end + let(:target_version) { "2.0.2" } + + it "returns the lowest security fix version" do + allow(checker).to receive(:lowest_security_fix_version).and_return( + Dependabot::Nub::Version.new(target_version) + ) + expect(lowest_resolvable_security_fix_version).to eq(Dependabot::Nub::Version.new(target_version)) + end + end + + context "when the dependency is not top-level" do + before { allow(dependency).to receive(:top_level?).and_return(false) } + + context "when there are conflicting dependencies" do + before { allow(checker).to receive(:conflicting_dependencies).and_return(["conflict"]) } + + it { is_expected.to be_nil } + end + + context "when there are no conflicting dependencies" do + before { allow(checker).to receive(:conflicting_dependencies).and_return([]) } + + it "returns the latest resolvable transitive security fix version with no unlock" do + allow(checker) + .to receive(:latest_resolvable_transitive_security_fix_version_with_no_unlock) + .and_return(Dependabot::Nub::Version.new(target_version)) + expect(lowest_resolvable_security_fix_version).to eq(Dependabot::Nub::Version.new(target_version)) + end + end + end + end + end + + describe "#latest_resolvable_version_with_no_unlock" do + subject { checker.latest_resolvable_version_with_no_unlock } + + context "with a non-git dependency" do + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: "1.0.0", + requirements: requirements, + package_manager: "nub" + ) + end + let(:requirements) do + [{ + file: "package.json", + requirement: req_string, + groups: [], + source: nil + }] + end + let(:req_string) { "^1.0.0" } + + it "delegates to PackageLatestVersionFinder" do + expect(described_class::PackageLatestVersionFinder).to receive(:new).with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + raise_on_ignored: false, + security_advisories: security_advisories, + cooldown_options: nil + ).and_call_original + + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq(Dependabot::Nub::Version.new("1.7.0")) + end + end + + context "when dealing with a sub-dependency" do + let(:dependency_name) { "@dependabot-fixtures/npm-transitive-dependency" } + let(:target_version) { "1.0.1" } + let(:dependency) do + Dependabot::Dependency.new( + name: dependency_name, + version: "1.0.0", + requirements: [], + package_manager: "nub" + ) + end + + it "delegates to SubdependencyVersionResolver" do + dummy_version_resolver = + instance_double(described_class::SubdependencyVersionResolver) + + expect(described_class::SubdependencyVersionResolver) + .to receive(:new) + .with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + ignored_versions: ignored_versions, + latest_allowable_version: Dependabot::Nub::Version.new("1.0.1"), + repo_contents_path: nil + ).and_return(dummy_version_resolver) + expect(dummy_version_resolver) + .to receive(:latest_resolvable_version) + .and_return(Dependabot::Nub::Version.new("1.0.0")) + + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq(Dependabot::Nub::Version.new("1.0.0")) + end + end + + context "with a git dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "is-number", + version: current_version, + requirements: [{ + requirement: req, + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: ref + } + }], + package_manager: "nub" + ) + end + let(:current_version) { "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8" } + + before do + git_url = "https://github.com/jonschlinkert/is-number.git" + git_header = { + "content-type" => "application/x-git-upload-pack-advertisement" + } + stub_request(:get, git_url + "/info/refs?service=git-upload-pack") + .with(basic_auth: %w(x-access-token token)) + .to_return( + status: 200, + body: fixture("git", "upload_packs", "is-number"), + headers: git_header + ) + end + + context "with a branch" do + let(:ref) { "master" } + let(:req) { nil } + + it "fetches the latest SHA-1 hash of the head of the branch" do + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq("0c6b15a88bc10cd47f67a09506399dfc9ddc075d") + end + end + + context "with a ref that looks like a version" do + let(:ref) { "2.0.0" } + let(:req) { nil } + + it "fetches the latest SHA-1 hash of the latest version tag" do + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq(current_version) + end + end + + context "with a requirement" do + let(:ref) { "master" } + let(:req) { "^2.0.0" } + + it "fetches the latest SHA-1 hash of the latest version tag" do + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq(current_version) + end + + context "when dealing with a numeric version" do + let(:current_version) { "2.0.2" } + + it "return a numeric version" do + expect(checker.latest_resolvable_version_with_no_unlock) + .to eq(Dependabot::Nub::Version.new("2.0.2")) + end + end + end + end + end + + describe "#latest_resolvable_previous_version" do + subject(:latest_resolvable_previous_version) do + checker.latest_resolvable_previous_version(updated_version) + end + + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + let(:updated_version) { Dependabot::Nub::Version.new("1.7.0") } + + it "delegates to VersionResolver" do + dummy_version_resolver = instance_double(described_class::VersionResolver) + + expect(described_class::VersionResolver) + .to receive(:new) + .with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + latest_version_finder: described_class::PackageLatestVersionFinder, + latest_allowable_version: updated_version, + repo_contents_path: nil, + dependency_group: nil, + raise_on_ignored: false, + update_cooldown: nil + ).and_return(dummy_version_resolver) + expect(dummy_version_resolver) + .to receive(:latest_resolvable_previous_version) + .with(updated_version) + .and_return(Dependabot::Nub::Version.new("1.6.0")) + + expect(latest_resolvable_previous_version) + .to eq(Dependabot::Nub::Version.new("1.6.0")) + end + end + + describe "#updated_requirements" do + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: dependency_version, + requirements: dependency_requirements, + package_manager: "nub" + ) + end + let(:dependency_requirements) do + [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }] + end + + it "delegates to the RequirementsUpdater" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: nil, + latest_resolvable_version: "1.7.0", + update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersions + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^1.7.0", + groups: [], + source: nil + }] + ) + end + + context "with a security vulnerability" do + let(:dependency_version) { "1.1.0" } + let(:security_advisories) do + [ + Dependabot::SecurityAdvisory.new( + dependency_name: "rails", + package_manager: "nub", + vulnerable_versions: ["~1.1.0", "1.2.0", "1.3.0"] + ) + ] + end + let(:target_version) { "1.2.1" } + + it "delegates to the RequirementsUpdater" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: nil, + latest_resolvable_version: "1.2.1", + update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersions + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^1.2.1", + groups: [], + source: nil + }] + ) + end + end + + context "when a requirements_update_strategy has been specified" do + let(:checker) do + described_class.new( + dependency: dependency, + dependency_files: dependency_files, + credentials: credentials, + ignored_versions: ignored_versions, + security_advisories: security_advisories, + requirements_update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary + ) + end + + it "uses the specified requirements_update_strategy" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: nil, + latest_resolvable_version: "1.7.0", + update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersionsIfNecessary + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }] + ) + end + end + + context "with a library (that has a lockfile)" do + # We've already stubbed hitting the registry for etag (since it's also + # the dependency we're checking in this spec) + let(:dependency_files) { project_dependency_files("javascript/etag_no_lockfile") } + + it "delegates to the RequirementsUpdater" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: nil, + latest_resolvable_version: "1.7.0", + update_strategy: Dependabot::RequirementsUpdateStrategy::WidenRanges + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }] + ) + end + end + + context "with a git dependency" do + let(:dependency) do + Dependabot::Dependency.new( + name: "is-number", + version: dependency_version, + requirements: dependency_requirements, + package_manager: "nub" + ) + end + let(:dependency_version) { "d5ac0584ee9ae7bd9288220a39780f155b9ad4c8" } + let(:dependency_requirements) do + [{ + requirement: "^2.0.0", + file: "package.json", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + } + }] + end + let(:registry_listing_url) { "https://registry.npmjs.org/is-number" } + let(:registry_response) do + fixture("npm_responses", "is_number.json") + end + let(:commit_compare_response) do + fixture("github", "commit_compare_diverged.json") + end + + before do + git_url = "https://github.com/jonschlinkert/is-number.git" + git_header = { + "content-type" => "application/x-git-upload-pack-advertisement" + } + stub_request(:get, git_url + "/info/refs?service=git-upload-pack") + .with(basic_auth: %w(x-access-token token)) + .to_return( + status: 200, + body: fixture("git", "upload_packs", "is-number"), + headers: git_header + ) + repo_url = "https://api.github.com/repos/jonschlinkert/is-number" + stub_request(:get, repo_url + "/compare/4.0.0...master") + .to_return( + status: 200, + body: commit_compare_response, + headers: { "Content-Type" => "application/json" } + ) + stub_request(:get, registry_listing_url + "/4.0.0") + .to_return(status: 200) + end + + it "delegates to the RequirementsUpdater" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + }, + latest_resolvable_version: "4.0.0", + update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersions + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^4.0.0", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + } + }] + ) + end + + context "with a version that looks like a number" do + let(:dependency_version) { "0.0.0" } + + it "delegates to the RequirementsUpdater" do + expect(described_class::RequirementsUpdater) + .to receive(:new) + .with( + requirements: dependency_requirements, + updated_source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + }, + latest_resolvable_version: "4.0.0", + update_strategy: Dependabot::RequirementsUpdateStrategy::BumpVersions + ) + .and_call_original + expect(checker.updated_requirements) + .to eq( + [{ + file: "package.json", + requirement: "^4.0.0", + groups: ["devDependencies"], + source: { + type: "git", + url: "https://github.com/jonschlinkert/is-number", + branch: nil, + ref: "master" + } + }] + ) + end + end + end + + context "with multiple requirements" do + let(:dependency) do + Dependabot::Dependency.new( + name: "@org/etag", + version: "1.0", + requirements: [ + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://registry.npmjs.org" + } + }, + { + file: "package.json", + requirement: "^1.0", + groups: [], + source: { + type: "registry", + url: "https://npm.fury.io/dependabot" + } + } + ], + package_manager: "nub" + ) + end + + before do + stub_request(:get, "https://npm.fury.io/dependabot/@org%2Fetag") + .and_return(status: 200, body: JSON.pretty_generate({})) + end + + it "prefers to private registry source" do + expect(checker.updated_requirements.first).to eq( + { + file: "package.json", + groups: [], + requirement: "^1.0", + source: { + type: "registry", + url: "https://npm.fury.io/dependabot" + } + } + ) + end + end + end + + describe "#requirements_unlocked_or_can_be?" do + subject { checker.requirements_unlocked_or_can_be? } + + it { is_expected.to be(true) } + + context "with the lockfile-only requirements update strategy set" do + let(:requirements_update_strategy) { Dependabot::RequirementsUpdateStrategy::LockfileOnly } + + it { is_expected.to be(false) } + end + end + + describe "#updated_dependencies_after_full_unlock" do + let(:dependency_files) { project_dependency_files("javascript/no_lockfile") } + let(:dependency) do + Dependabot::Dependency.new( + name: "etag", + version: dependency_version, + requirements: dependency_requirements, + package_manager: "nub" + ) + end + let(:dependency_requirements) do + [{ + file: "package.json", + requirement: "^1.0.0", + groups: [], + source: nil + }] + end + + it "delegates to the VersionResolver" do + dummy_version_resolver = instance_double(described_class::VersionResolver) + + expect(described_class::VersionResolver) + .to receive(:new) + .with( + dependency: dependency, + credentials: credentials, + dependency_files: dependency_files, + latest_version_finder: described_class::PackageLatestVersionFinder, + latest_allowable_version: Dependabot::Nub::Version.new("1.7.0"), + repo_contents_path: nil, + dependency_group: nil, + raise_on_ignored: false, + update_cooldown: nil + ).and_return(dummy_version_resolver) + expect(dummy_version_resolver) + .to receive(:dependency_updates_from_full_unlock) + .and_return( + [{ + dependency: Dependabot::Dependency.new( + name: "etag", + version: nil, + package_manager: "nub", + requirements: [{ + file: "package.json", + requirement: "^1.6.0", + groups: ["dependencies"], + source: nil + }] + ), + version: Dependabot::Nub::Version.new("1.7.0"), + previous_version: nil + }] + ) + + expect(checker.send(:updated_dependencies_after_full_unlock).first) + .to eq( + Dependabot::Dependency.new( + name: "etag", + version: "1.7.0", + package_manager: "nub", + previous_version: nil, + requirements: [{ + file: "package.json", + requirement: "^1.7.0", + groups: ["dependencies"], + source: nil + }], + previous_requirements: [{ + file: "package.json", + requirement: "^1.6.0", + groups: ["dependencies"], + source: nil + }] + ) + ) + end + end +end diff --git a/nub/spec/dependabot/nub/version_spec.rb b/nub/spec/dependabot/nub/version_spec.rb new file mode 100644 index 00000000000..53bfbe363f1 --- /dev/null +++ b/nub/spec/dependabot/nub/version_spec.rb @@ -0,0 +1,321 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub/version" + +RSpec.describe Dependabot::Nub::Version do + subject(:version) { described_class.new(version_string) } + + let(:version_string) { "1.0.0" } + + describe ".correct?" do + subject { described_class.correct?(version_string) } + + context "with a string prefixed with a 'v'" do + let(:version_string) { "v1.0.0" } + + it { is_expected.to be(true) } + end + + context "with a string not prefixed with a 'v'" do + let(:version_string) { "1.0.0" } + + it { is_expected.to be(true) } + end + + context "with build metadata" do + let(:version_string) { "1.0.0+some-metadata" } + + it { is_expected.to be(true) } + end + + context "with an invalid string" do + let(:version_string) { "va1.0.0" } + + it { is_expected.to be(false) } + end + end + + describe ".new" do + subject { described_class.new(version_string) } + + context "with a version class" do + let(:version_string) { described_class.new("1.0.0") } + + it { is_expected.to eq(described_class.new("1.0.0")) } + end + end + + describe "#to_s" do + subject { version.to_s } + + context "with a non-prerelease" do + let(:version_string) { "1.0.0" } + + it { is_expected.to eq "1.0.0" } + end + + context "with a normal prerelease" do + let(:version_string) { "1.0.0.pre1" } + + it { is_expected.to eq "1.0.0.pre1" } + end + + context "with a JS-style prerelease" do + let(:version_string) { "1.0.0-pre1" } + + it { is_expected.to eq "1.0.0-pre1" } + end + + context "with build metadata" do + let(:version_string) { "1.0.0+some-metadata" } + + it { is_expected.to eq "1.0.0+some-metadata" } + end + end + + describe "#major" do + subject { version.major } + + context "with major, minor, patch, and prerelease" do + let(:version_string) { "1.2.3.pre1" } + + it { is_expected.to eq 1 } + end + + context "with major, minor, and patch" do + let(:version_string) { "1.2.3" } + + it { is_expected.to eq 1 } + end + + context "with major and minor" do + let(:version_string) { "1.2" } + + it { is_expected.to eq 1 } + end + + context "with major" do + let(:version_string) { "1" } + + it { is_expected.to eq 1 } + end + + context "with blank" do + let(:version_string) { "" } + + it { is_expected.to eq 0 } + end + end + + describe "#minor" do + subject { version.minor } + + context "with major, minor, patch, and prerelease" do + let(:version_string) { "1.2.3.pre1" } + + it { is_expected.to eq 2 } + end + + context "with major, minor, and patch" do + let(:version_string) { "1.2.3" } + + it { is_expected.to eq 2 } + end + + context "with major and minor" do + let(:version_string) { "1.2" } + + it { is_expected.to eq 2 } + end + + context "with major" do + let(:version_string) { "1" } + + it { is_expected.to eq 0 } + end + + context "with blank" do + let(:version_string) { "" } + + it { is_expected.to eq 0 } + end + end + + describe "#patch" do + subject { version.patch } + + context "with major, minor, patch, and prerelease" do + let(:version_string) { "1.2.3.pre1" } + + it { is_expected.to eq 3 } + end + + context "with major, minor, and patch" do + let(:version_string) { "1.2.3" } + + it { is_expected.to eq 3 } + end + + context "with major and minor" do + let(:version_string) { "1.2" } + + it { is_expected.to eq 0 } + end + + context "with major" do + let(:version_string) { "1" } + + it { is_expected.to eq 0 } + end + + context "with blank" do + let(:version_string) { "" } + + it { is_expected.to eq 0 } + end + end + + describe "#backwards_compatible_with?" do + subject { version.backwards_compatible_with?(other_version) } + + let(:other_version) { described_class.new(other_version_string) } + + context "when comparing same version" do + let(:version_string) { "1.2.3.pre1" } + let(:other_version_string) { version_string } + + it { is_expected.to be true } + end + + context "when comparing same version with different prerelease" do + let(:version_string) { "1.2.3.pre1" } + let(:other_version_string) { "1.2.3.pre2" } + + it { is_expected.to be true } + end + + context "when comparing version with later patch" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.2.4" } + + it { is_expected.to be true } + end + + context "when comparing version with earlier patch" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.2.2" } + + it { is_expected.to be true } + end + + context "when comparing version with zero patch" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.2.0" } + + it { is_expected.to be true } + end + + context "when comparing version with omitted patch" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.2" } + + it { is_expected.to be true } + end + + context "when comparing version with earlier minor" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.1" } + + it { is_expected.to be true } + end + + context "when comparing version with later minor" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "1.3" } + + it { is_expected.to be false } + end + + context "when comparing version with earlier major" do + let(:version_string) { "2.3.4" } + let(:other_version_string) { "1.2.3" } + + it { is_expected.to be false } + end + + context "when comparing version with later major" do + let(:version_string) { "1.2.3" } + let(:other_version_string) { "2.3.4" } + + it { is_expected.to be false } + end + + context "when comparing same versions with zero major" do + let(:version_string) { "0.2.1" } + let(:other_version_string) { "0.2.1" } + + it { is_expected.to be true } + end + + context "when comparing earlier version with zero major" do + let(:version_string) { "0.2.1" } + let(:other_version_string) { "0.2.0" } + + it { is_expected.to be false } + end + + context "when comparing later version with zero major" do + let(:version_string) { "0.2.1" } + let(:other_version_string) { "0.2.2" } + + it { is_expected.to be false } + end + end + + describe "compatibility with Gem::Requirement" do + subject { requirement.satisfied_by?(version) } + + let(:requirement) { Gem::Requirement.new(">= 1.0.0") } + + context "with a greater version" do + let(:version_string) { "1.0.0" } + + it { is_expected.to be(true) } + end + + context "with an lesser version" do + let(:version_string) { "0.9.0" } + + it { is_expected.to be(false) } + end + + context "with a valid prerelease version" do + let(:version_string) { "1.1.0-pre" } + + it { is_expected.to be(true) } + end + + context "when prefixed with a 'v'" do + context "with a greater version" do + let(:version_string) { "v1.1.0" } + + it { is_expected.to be(true) } + end + + context "with an lesser version" do + let(:version_string) { "v0.9.0" } + + it { is_expected.to be(false) } + end + end + + context "with build metadata" do + let(:requirement) { Gem::Requirement.new("1.0.0") } + let(:version_string) { "1.0.0+build-metadata" } + + it { is_expected.to be(true) } + end + end +end diff --git a/nub/spec/dependabot/nub_spec.rb b/nub/spec/dependabot/nub_spec.rb new file mode 100644 index 00000000000..a9b54f714e6 --- /dev/null +++ b/nub/spec/dependabot/nub_spec.rb @@ -0,0 +1,10 @@ +# typed: false +# frozen_string_literal: true + +require "spec_helper" +require "dependabot/nub" +require_common_spec "shared_examples_for_autoloading" + +RSpec.describe Dependabot::Nub do + it_behaves_like "it registers the required classes", "nub" +end diff --git a/nub/spec/fixtures/gemfury_responses/gemfury_response_etag.json b/nub/spec/fixtures/gemfury_responses/gemfury_response_etag.json new file mode 100644 index 00000000000..1552f36f0bc --- /dev/null +++ b/nub/spec/fixtures/gemfury_responses/gemfury_response_etag.json @@ -0,0 +1,119 @@ +{ + "_id": "etag", + "name": "etag", + "dist-tags": { + "latest": "1.8.1" + }, + "versions": { + "1.8.1": { + "name": "etag", + "description": "Create simple HTTP ETags", + "version": "1.8.1", + "contributors": [ + "Douglas Christopher Wilson ", + "David Björklund " + ], + "bugs": { + "url": "https://github.com/jshttp/etag/issues" + }, + "license": "MIT", + "keywords": [ + "etag", + "http", + "res" + ], + "repository": "jshttp/etag", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", + "eslint": "3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "1.21.5", + "safe-buffer": "5.1.1", + "seedrandom": "2.4.3" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "bench": "node benchmark/index.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "_id": "etag@1.8.1", + "dist": { + "shasum": "6a21748bc0860b08f7c68f6a82605e9d626f1267", + "tarball": "fury-repo:/~/d/etag/etag-1.8.1" + } + }, + "1.8.0": { + "name": "etag", + "description": "Create simple HTTP ETags", + "version": "1.8.0", + "contributors": [ + "Douglas Christopher Wilson ", + "David Björklund " + ], + "bugs": { + "url": "https://github.com/jshttp/etag/issues" + }, + "license": "MIT", + "keywords": [ + "etag", + "http", + "res" + ], + "repository": "jshttp/etag", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", + "eslint": "3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "1.21.5", + "safe-buffer": "5.1.1", + "seedrandom": "2.4.3" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "README.md", + "index.js" + ], + "engines": { + "node": ">= 0.6" + }, + "scripts": { + "bench": "node benchmark/index.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "_id": "etag@1.8.0", + "dist": { + "shasum": "6a21748bc0860b08f7c68f6a82605e9d626f1267", + "tarball": "fury-repo:/~/d/etag/etag-1.8.0" + } + } + } +} diff --git a/nub/spec/fixtures/git/upload_packs/is-number b/nub/spec/fixtures/git/upload_packs/is-number new file mode 100644 index 00000000000..07b111b2733 Binary files /dev/null and b/nub/spec/fixtures/git/upload_packs/is-number differ diff --git a/nub/spec/fixtures/git/upload_packs/no_tags b/nub/spec/fixtures/git/upload_packs/no_tags new file mode 100644 index 00000000000..2c8f47b9b5d Binary files /dev/null and b/nub/spec/fixtures/git/upload_packs/no_tags differ diff --git a/nub/spec/fixtures/github/commit_compare_diverged.json b/nub/spec/fixtures/github/commit_compare_diverged.json new file mode 100644 index 00000000000..a6540c8ff19 --- /dev/null +++ b/nub/spec/fixtures/github/commit_compare_diverged.json @@ -0,0 +1,454 @@ +{ + "url": "https://api.github.com/repos/gocardless/business/compare/v1.10.0...rubocop", + "html_url": "https://github.com/gocardless/business/compare/v1.10.0...rubocop", + "permalink_url": "https://github.com/gocardless/business/compare/gocardless:d31e445...gocardless:ace90dc", + "diff_url": "https://github.com/gocardless/business/compare/v1.10.0...rubocop.diff", + "patch_url": "https://github.com/gocardless/business/compare/v1.10.0...rubocop.patch", + "base_commit": { + "sha": "d31e445215b5af70c1604715d97dd953e868380e", + "commit": { + "author": { + "name": "Jay Shah", + "email": "jay@gocardless.com", + "date": "2017-09-20T16:47:06Z" + }, + "committer": { + "name": "Jay Shah", + "email": "hey@jay.sh", + "date": "2017-09-21T08:44:04Z" + }, + "message": "Make code more readable.", + "tree": { + "sha": "6624d2e3f805e27a79fbc2d3be02a5c8e2ea6e35", + "url": "https://api.github.com/repos/gocardless/business/git/trees/6624d2e3f805e27a79fbc2d3be02a5c8e2ea6e35" + }, + "url": "https://api.github.com/repos/gocardless/business/git/commits/d31e445215b5af70c1604715d97dd953e868380e", + "comment_count": 0 + }, + "url": "https://api.github.com/repos/gocardless/business/commits/d31e445215b5af70c1604715d97dd953e868380e", + "html_url": "https://github.com/gocardless/business/commit/d31e445215b5af70c1604715d97dd953e868380e", + "comments_url": "https://api.github.com/repos/gocardless/business/commits/d31e445215b5af70c1604715d97dd953e868380e/comments", + "author": { + "login": "jaysh", + "id": 4825223, + "avatar_url": "https://avatars1.githubusercontent.com/u/4825223?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jaysh", + "html_url": "https://github.com/jaysh", + "followers_url": "https://api.github.com/users/jaysh/followers", + "following_url": "https://api.github.com/users/jaysh/following{/other_user}", + "gists_url": "https://api.github.com/users/jaysh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jaysh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jaysh/subscriptions", + "organizations_url": "https://api.github.com/users/jaysh/orgs", + "repos_url": "https://api.github.com/users/jaysh/repos", + "events_url": "https://api.github.com/users/jaysh/events{/privacy}", + "received_events_url": "https://api.github.com/users/jaysh/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "jaysh", + "id": 4825223, + "avatar_url": "https://avatars1.githubusercontent.com/u/4825223?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jaysh", + "html_url": "https://github.com/jaysh", + "followers_url": "https://api.github.com/users/jaysh/followers", + "following_url": "https://api.github.com/users/jaysh/following{/other_user}", + "gists_url": "https://api.github.com/users/jaysh/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jaysh/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jaysh/subscriptions", + "organizations_url": "https://api.github.com/users/jaysh/orgs", + "repos_url": "https://api.github.com/users/jaysh/repos", + "events_url": "https://api.github.com/users/jaysh/events{/privacy}", + "received_events_url": "https://api.github.com/users/jaysh/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "fcc5d35d3a5ff9a4ba16178a5442c3c105ffacdb", + "url": "https://api.github.com/repos/gocardless/business/commits/fcc5d35d3a5ff9a4ba16178a5442c3c105ffacdb", + "html_url": "https://github.com/gocardless/business/commit/fcc5d35d3a5ff9a4ba16178a5442c3c105ffacdb" + } + ] + }, + "merge_base_commit": { + "sha": "20984b51291e25782bb55ef72008bed592c4c2d7", + "commit": { + "author": { + "name": "Matt Thomson", + "email": "mattjohnthomson@gmail.com", + "date": "2017-02-13T17:45:42Z" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com", + "date": "2017-02-13T17:45:42Z" + }, + "message": "Merge pull request #18 from gocardless/bump-version-to-1.8.0\n\nBump version to 1.8.0", + "tree": { + "sha": "8b2c15faf83aba6803c457ff420740964b701647", + "url": "https://api.github.com/repos/gocardless/business/git/trees/8b2c15faf83aba6803c457ff420740964b701647" + }, + "url": "https://api.github.com/repos/gocardless/business/git/commits/20984b51291e25782bb55ef72008bed592c4c2d7", + "comment_count": 0 + }, + "url": "https://api.github.com/repos/gocardless/business/commits/20984b51291e25782bb55ef72008bed592c4c2d7", + "html_url": "https://github.com/gocardless/business/commit/20984b51291e25782bb55ef72008bed592c4c2d7", + "comments_url": "https://api.github.com/repos/gocardless/business/commits/20984b51291e25782bb55ef72008bed592c4c2d7/comments", + "author": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "web-flow", + "id": 19864447, + "avatar_url": "https://avatars3.githubusercontent.com/u/19864447?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/web-flow", + "html_url": "https://github.com/web-flow", + "followers_url": "https://api.github.com/users/web-flow/followers", + "following_url": "https://api.github.com/users/web-flow/following{/other_user}", + "gists_url": "https://api.github.com/users/web-flow/gists{/gist_id}", + "starred_url": "https://api.github.com/users/web-flow/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/web-flow/subscriptions", + "organizations_url": "https://api.github.com/users/web-flow/orgs", + "repos_url": "https://api.github.com/users/web-flow/repos", + "events_url": "https://api.github.com/users/web-flow/events{/privacy}", + "received_events_url": "https://api.github.com/users/web-flow/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "39154565de7bac59f915f26fce8f6124edf37ac2", + "url": "https://api.github.com/repos/gocardless/business/commits/39154565de7bac59f915f26fce8f6124edf37ac2", + "html_url": "https://github.com/gocardless/business/commit/39154565de7bac59f915f26fce8f6124edf37ac2" + }, + { + "sha": "beb4c78337428270f6fd0c1f34ef5cddc3870bd5", + "url": "https://api.github.com/repos/gocardless/business/commits/beb4c78337428270f6fd0c1f34ef5cddc3870bd5", + "html_url": "https://github.com/gocardless/business/commit/beb4c78337428270f6fd0c1f34ef5cddc3870bd5" + } + ] + }, + "status": "diverged", + "ahead_by": 3, + "behind_by": 10, + "total_commits": 3, + "commits": [ + { + "sha": "8269023ded834032be24695843462544b12b86c0", + "commit": { + "author": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:51:02Z" + }, + "committer": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:57:10Z" + }, + "message": "Add Rubocop, autocorrect offences", + "tree": { + "sha": "4bfbaced394069733d8954d2aac9634e3e3aac98", + "url": "https://api.github.com/repos/gocardless/business/git/trees/4bfbaced394069733d8954d2aac9634e3e3aac98" + }, + "url": "https://api.github.com/repos/gocardless/business/git/commits/8269023ded834032be24695843462544b12b86c0", + "comment_count": 0 + }, + "url": "https://api.github.com/repos/gocardless/business/commits/8269023ded834032be24695843462544b12b86c0", + "html_url": "https://github.com/gocardless/business/commit/8269023ded834032be24695843462544b12b86c0", + "comments_url": "https://api.github.com/repos/gocardless/business/commits/8269023ded834032be24695843462544b12b86c0/comments", + "author": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "20984b51291e25782bb55ef72008bed592c4c2d7", + "url": "https://api.github.com/repos/gocardless/business/commits/20984b51291e25782bb55ef72008bed592c4c2d7", + "html_url": "https://github.com/gocardless/business/commit/20984b51291e25782bb55ef72008bed592c4c2d7" + } + ] + }, + { + "sha": "59532c6733053073a8ee905224874584a4f1d5a9", + "commit": { + "author": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:53:49Z" + }, + "committer": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:57:10Z" + }, + "message": "Fix Lint/Loop cop", + "tree": { + "sha": "6dd5c0c2e3e497819766294529b23d5f83a444f8", + "url": "https://api.github.com/repos/gocardless/business/git/trees/6dd5c0c2e3e497819766294529b23d5f83a444f8" + }, + "url": "https://api.github.com/repos/gocardless/business/git/commits/59532c6733053073a8ee905224874584a4f1d5a9", + "comment_count": 0 + }, + "url": "https://api.github.com/repos/gocardless/business/commits/59532c6733053073a8ee905224874584a4f1d5a9", + "html_url": "https://github.com/gocardless/business/commit/59532c6733053073a8ee905224874584a4f1d5a9", + "comments_url": "https://api.github.com/repos/gocardless/business/commits/59532c6733053073a8ee905224874584a4f1d5a9/comments", + "author": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "8269023ded834032be24695843462544b12b86c0", + "url": "https://api.github.com/repos/gocardless/business/commits/8269023ded834032be24695843462544b12b86c0", + "html_url": "https://github.com/gocardless/business/commit/8269023ded834032be24695843462544b12b86c0" + } + ] + }, + { + "sha": "ace90dc4d34136a5d9570e54288c505711fb93ce", + "commit": { + "author": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:55:55Z" + }, + "committer": { + "name": "Matt Thomson", + "email": "mattthomson@gocardless.com", + "date": "2017-06-05T17:57:10Z" + }, + "message": "Fix Style/AccessorMethodName cop", + "tree": { + "sha": "f1a9e131b916b9d71c088be3c835a8ce6862ba61", + "url": "https://api.github.com/repos/gocardless/business/git/trees/f1a9e131b916b9d71c088be3c835a8ce6862ba61" + }, + "url": "https://api.github.com/repos/gocardless/business/git/commits/ace90dc4d34136a5d9570e54288c505711fb93ce", + "comment_count": 0 + }, + "url": "https://api.github.com/repos/gocardless/business/commits/ace90dc4d34136a5d9570e54288c505711fb93ce", + "html_url": "https://github.com/gocardless/business/commit/ace90dc4d34136a5d9570e54288c505711fb93ce", + "comments_url": "https://api.github.com/repos/gocardless/business/commits/ace90dc4d34136a5d9570e54288c505711fb93ce/comments", + "author": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "committer": { + "login": "matt-thomson", + "id": 771863, + "avatar_url": "https://avatars3.githubusercontent.com/u/771863?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/matt-thomson", + "html_url": "https://github.com/matt-thomson", + "followers_url": "https://api.github.com/users/matt-thomson/followers", + "following_url": "https://api.github.com/users/matt-thomson/following{/other_user}", + "gists_url": "https://api.github.com/users/matt-thomson/gists{/gist_id}", + "starred_url": "https://api.github.com/users/matt-thomson/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/matt-thomson/subscriptions", + "organizations_url": "https://api.github.com/users/matt-thomson/orgs", + "repos_url": "https://api.github.com/users/matt-thomson/repos", + "events_url": "https://api.github.com/users/matt-thomson/events{/privacy}", + "received_events_url": "https://api.github.com/users/matt-thomson/received_events", + "type": "User", + "site_admin": false + }, + "parents": [ + { + "sha": "59532c6733053073a8ee905224874584a4f1d5a9", + "url": "https://api.github.com/repos/gocardless/business/commits/59532c6733053073a8ee905224874584a4f1d5a9", + "html_url": "https://github.com/gocardless/business/commit/59532c6733053073a8ee905224874584a4f1d5a9" + } + ] + } + ], + "files": [ + { + "sha": "1c1db850defccb268f960ff4a47f0e3afd898dc5", + "filename": ".rubocop.yml", + "status": "added", + "additions": 122, + "deletions": 0, + "changes": 122, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/.rubocop.yml", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/.rubocop.yml", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/.rubocop.yml?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -0,0 +1,122 @@\n+AllCops:\n+ TargetRubyVersion: 2.1\n+ DisplayCopNames: true\n+\n+Lint/UnneededDisable:\n+ Severity: error\n+\n+Metrics/AbcSize:\n+ Max: 59\n+\n+Metrics/CyclomaticComplexity:\n+ Max: 10\n+\n+Metrics/PerceivedComplexity:\n+ Max: 9\n+\n+Metrics/ClassLength:\n+ Enabled: false\n+\n+Layout/LineLength:\n+ Max: 90\n+ Exclude:\n+ - Gemfile\n+\n+Metrics/BlockLength:\n+ Exclude:\n+ - business.gemspec\n+ - spec/*\n+ - spec/**/*\n+\n+# Avoid methods longer than 30 lines of code\n+Metrics/MethodLength:\n+ CountComments: false # count full line comments?\n+ Max: 87\n+\n+Metrics/ModuleLength:\n+ Enabled: false\n+\n+Metrics/ParameterLists:\n+ CountKeywordArgs: false\n+\n+# Allow non-ASCII characters (e.g. £) in comments\n+Style/AsciiComments:\n+ Enabled: false\n+\n+Style/Alias:\n+ Enabled: true\n+ EnforcedStyle: prefer_alias_method\n+\n+# Use trailing rather than leading dots on multi-line call chains\n+Style/DotPosition:\n+ EnforcedStyle: trailing\n+\n+# Magic encoding comment only relevant on ruby-1.9 or non-utf8\n+Style/Encoding:\n+ Enabled: never\n+\n+Style/Documentation:\n+ Enabled: false\n+\n+Style/FormatString:\n+ EnforcedStyle: sprintf\n+\n+Style/FrozenStringLiteralComment:\n+ Enabled: always\n+\n+Style/TrailingCommaInLiteral:\n+ EnforcedStyleForMultiline: comma\n+\n+Style/TrailingCommaInArguments:\n+ EnforcedStyleForMultiline: comma\n+\n+# As of 0.43.0 this cop complains in situations where a guard clause would be\n+# unhelpful or erroneous.\n+# The auto-correct is also buggy.\n+Style/GuardClause:\n+ Enabled: false\n+\n+Style/IndentArray:\n+ EnforcedStyle: consistent\n+\n+Style/IndentHash:\n+ EnforcedStyle: consistent\n+\n+Style/Lambda:\n+ EnforcedStyle: literal\n+\n+Style/MultilineMethodCallIndentation:\n+ EnforcedStyle: indented\n+\n+Style/MultilineOperationIndentation:\n+ EnforcedStyle: indented\n+\n+Style/NumericPredicate:\n+ Exclude:\n+ - 'spec/**/*'\n+\n+Style/NumericLiterals:\n+ MinDigits: 11\n+\n+# As of 0.43.0 this cop has many false positives\n+# https://github.com/bbatsov/rubocop/pull/3517 may fix a lot of these\n+Style/SafeNavigation:\n+ Enabled: false\n+\n+Style/SignalException:\n+ EnforcedStyle: 'only_raise'\n+\n+# Wants you to use the same argument names for every reduce. This seems kinda\n+# naff compared to naming them semantically\n+Style/SingleLineBlockParams:\n+ Enabled: false\n+\n+Style/StringLiterals:\n+ EnforcedStyle: 'double_quotes'\n+\n+Style/VariableNumber:\n+ Enabled: false\n+\n+Style/FileName:\n+ Exclude:\n+ - 'Gemfile'" + }, + { + "sha": "b4e2a20bb6069d33479542fc863e7e36810e0f01", + "filename": "Gemfile", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/Gemfile", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/Gemfile", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/Gemfile?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -1,3 +1,3 @@\n-source 'https://rubygems.org'\n+source \"https://rubygems.org\"\n \n gemspec" + }, + { + "sha": "a865ee8ed704d8f89d45fbdde6d71f8ba16818d9", + "filename": "business.gemspec", + "status": "modified", + "additions": 6, + "deletions": 6, + "changes": 12, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/business.gemspec", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/business.gemspec", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/business.gemspec?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -1,23 +1,23 @@\n-# coding: utf-8\n-lib = File.expand_path('../lib', __FILE__)\n+lib = File.expand_path(\"../lib\", __FILE__)\n $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)\n-require 'business/version'\n+require \"business/version\"\n \n Gem::Specification.new do |spec|\n spec.name = \"business\"\n spec.version = Business::VERSION\n spec.authors = [\"Harry Marr\"]\n spec.email = [\"developers@gocardless.com\"]\n- spec.summary = %q{Date calculations based on business calendars}\n- spec.description = %q{Date calculations based on business calendars}\n+ spec.summary = \"Date calculations based on business calendars\"\n+ spec.description = \"Date calculations based on business calendars\"\n spec.homepage = \"https://github.com/gocardless/business\"\n spec.licenses = [\"MIT\"]\n \n- spec.files = `git ls-files`.split($/)\n+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)\n spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }\n spec.test_files = spec.files.grep(%r{^(test|spec|features)/})\n spec.require_paths = [\"lib\"]\n \n spec.add_development_dependency \"bundler\", \"~> 1.3\"\n spec.add_development_dependency \"rspec\", \"~> 3.1\"\n+ spec.add_development_dependency \"rubocop\", \"~> 0.49.1\"\n end" + }, + { + "sha": "9b9f15d9ef5ad322cbb2d36a7b24d744fa4da2c2", + "filename": "lib/business.rb", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business.rb", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business.rb", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/lib/business.rb?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -1 +1 @@\n-require 'business/calendar'\n+require \"business/calendar\"" + }, + { + "sha": "9c1286a151f1762c071ebd35c8099c6bdceec7b1", + "filename": "lib/business/calendar.rb", + "status": "modified", + "additions": 25, + "deletions": 29, + "changes": 54, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business/calendar.rb", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business/calendar.rb", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/lib/business/calendar.rb?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -1,4 +1,4 @@\n-require 'yaml'\n+require \"yaml\"\n \n module Business\n class Calendar\n@@ -8,45 +8,43 @@ class << self\n \n def self.calendar_directories\n directories = @additional_load_paths || []\n- directories + [File.join(File.dirname(__FILE__), 'data')]\n+ directories + [File.join(File.dirname(__FILE__), \"data\")]\n end\n private_class_method :calendar_directories\n \n def self.load(calendar)\n directory = calendar_directories.find do |dir|\n- File.exists?(File.join(dir, \"#{calendar}.yml\"))\n+ File.exist?(File.join(dir, \"#{calendar}.yml\"))\n end\n raise \"No such calendar '#{calendar}'\" unless directory\n \n yaml = YAML.load_file(File.join(directory, \"#{calendar}.yml\"))\n- self.new(holidays: yaml['holidays'], working_days: yaml['working_days'])\n+ new(holidays: yaml[\"holidays\"], working_days: yaml[\"working_days\"])\n end\n \n @lock = Mutex.new\n def self.load_cached(calendar)\n @lock.synchronize do\n- @cache ||= { }\n- unless @cache.include?(calendar)\n- @cache[calendar] = self.load(calendar)\n- end\n+ @cache ||= {}\n+ @cache[calendar] = load(calendar) unless @cache.include?(calendar)\n @cache[calendar]\n end\n end\n \n- DAY_NAMES = %( mon tue wed thu fri sat sun )\n+ DAY_NAMES = %( mon tue wed thu fri sat sun ).freeze\n \n attr_reader :working_days, :holidays\n \n def initialize(config)\n- set_working_days(config[:working_days])\n- set_holidays(config[:holidays])\n+ self.working_days = config[:working_days]\n+ self.holidays = config[:holidays]\n end\n \n # Return true if the date given is a business day (typically that means a\n # non-weekend day) and not a holiday.\n def business_day?(date)\n date = date.to_date\n- return false unless working_days.include?(date.strftime('%a').downcase)\n+ return false unless working_days.include?(date.strftime(\"%a\").downcase)\n return false if holidays.include?(date)\n true\n end\n@@ -70,18 +68,20 @@ def roll_backward(date)\n # Roll forward to the next business day regardless of whether the given\n # date is a business day or not.\n def next_business_day(date)\n- begin\n+ loop do\n date += day_interval_for(date)\n- end until business_day?(date)\n+ break if business_day?(date)\n+ end\n date\n end\n \n # Roll backward to the previous business day regardless of whether the given\n # date is a business day or not.\n def previous_business_day(date)\n- begin\n+ loop do\n date -= day_interval_for(date)\n- end until business_day?(date)\n+ break if business_day?(date)\n+ end\n date\n end\n \n@@ -93,9 +93,7 @@ def previous_business_day(date)\n def add_business_days(date, delta)\n date = roll_forward(date)\n delta.times do\n- begin\n- date += day_interval_for(date)\n- end until business_day?(date)\n+ date = next_business_day(date)\n end\n date\n end\n@@ -108,9 +106,7 @@ def add_business_days(date, delta)\n def subtract_business_days(date, delta)\n date = roll_backward(date)\n delta.times do\n- begin\n- date -= day_interval_for(date)\n- end until business_day?(date)\n+ date = previous_business_day(date)\n end\n date\n end\n@@ -119,7 +115,8 @@ def subtract_business_days(date, delta)\n # This method counts from start of date1 to start of date2. So,\n # business_days_between(mon, weds) = 2 (assuming no holidays)\n def business_days_between(date1, date2)\n- date1, date2 = date1.to_date, date2.to_date\n+ date1 = date1.to_date\n+ date2 = date2.to_date\n \n # To optimise this method we split the range into full weeks and a\n # remaining period.\n@@ -141,11 +138,11 @@ def business_days_between(date1, date2)\n num_biz_days -= holidays.count do |holiday|\n in_range = full_weeks_range.cover?(holiday)\n # Only pick a holiday if its on a working day (e.g., not a weekend)\n- on_biz_day = working_days.include?(holiday.strftime('%a').downcase)\n+ on_biz_day = working_days.include?(holiday.strftime(\"%a\").downcase)\n in_range && on_biz_day\n end\n \n- remaining_range = (date2-remaining_days...date2)\n+ remaining_range = (date2 - remaining_days...date2)\n # Loop through each day in remaining_range and count if a business day\n num_biz_days + remaining_range.count { |a| business_day?(a) }\n end\n@@ -155,7 +152,7 @@ def day_interval_for(date)\n end\n \n # Internal method for assigning working days from a calendar config.\n- def set_working_days(working_days)\n+ def working_days=(working_days)\n @working_days = (working_days || default_working_days).map do |day|\n day.downcase.strip[0..2].tap do |normalised_day|\n raise \"Invalid day #{day}\" unless DAY_NAMES.include?(normalised_day)\n@@ -164,14 +161,13 @@ def set_working_days(working_days)\n end\n \n # Internal method for assigning holidays from a calendar config.\n- def set_holidays(holidays)\n+ def holidays=(holidays)\n @holidays = (holidays || []).map { |holiday| Date.parse(holiday) }\n end\n \n # If no working days are provided in the calendar config, these are used.\n def default_working_days\n- %w( mon tue wed thu fri )\n+ %w[mon tue wed thu fri]\n end\n end\n end\n-" + }, + { + "sha": "a9660d509b677e0f9b22b93a130e725ea58bcf33", + "filename": "lib/business/version.rb", + "status": "modified", + "additions": 1, + "deletions": 1, + "changes": 2, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business/version.rb", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/lib/business/version.rb", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/lib/business/version.rb?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -1,3 +1,3 @@\n module Business\n- VERSION = \"1.8.0\"\n+ VERSION = \"1.8.0\".freeze\n end" + }, + { + "sha": "628f77d81a1fbf6b7061b6570dfa0ed02f7988c2", + "filename": "spec/calendar_spec.rb", + "status": "modified", + "additions": 9, + "deletions": 13, + "changes": 22, + "blob_url": "https://github.com/gocardless/business/blob/ace90dc4d34136a5d9570e54288c505711fb93ce/spec/calendar_spec.rb", + "raw_url": "https://github.com/gocardless/business/raw/ace90dc4d34136a5d9570e54288c505711fb93ce/spec/calendar_spec.rb", + "contents_url": "https://api.github.com/repos/gocardless/business/contents/spec/calendar_spec.rb?ref=ace90dc4d34136a5d9570e54288c505711fb93ce", + "patch": "@@ -24,7 +24,7 @@\n context \"when given a calendar from a custom directory\" do\n before do\n Business::Calendar.additional_load_paths = [\n- File.join(File.dirname(__FILE__), 'fixtures', 'calendars')\n+ File.join(File.dirname(__FILE__), \"fixtures\", \"calendars\"),\n ]\n end\n after { Business::Calendar.additional_load_paths = nil }\n@@ -55,29 +55,29 @@\n end\n end\n \n- describe \"#set_working_days\" do\n+ describe \"#working_days=\" do\n let(:calendar) { Business::Calendar.new({}) }\n let(:working_days) { [] }\n- subject { calendar.set_working_days(working_days) }\n+ subject { calendar.working_days = working_days }\n \n context \"when given valid working days\" do\n- let(:working_days) { %w( mon fri ) }\n+ let(:working_days) { %w[mon fri] }\n before { subject }\n \n it \"assigns them\" do\n expect(calendar.working_days).to eq(working_days)\n end\n \n context \"that are unnormalised\" do\n- let(:working_days) { %w( Monday Friday ) }\n+ let(:working_days) { %w[Monday Friday] }\n it \"normalises them\" do\n- expect(calendar.working_days).to eq(%w( mon fri ))\n+ expect(calendar.working_days).to eq(%w[mon fri])\n end\n end\n end\n \n context \"when given an invalid business day\" do\n- let(:working_days) { %w( Notaday ) }\n+ let(:working_days) { %w[Notaday] }\n specify { expect { subject }.to raise_error(/Invalid day/) }\n end\n \n@@ -89,10 +89,10 @@\n end\n end\n \n- describe \"#set_holidays\" do\n+ describe \"#holidays=\" do\n let(:calendar) { Business::Calendar.new({}) }\n let(:holidays) { [] }\n- before { calendar.set_holidays(holidays) }\n+ before { calendar.holidays = holidays }\n subject { calendar.holidays }\n \n context \"when given valid business days\" do\n@@ -300,7 +300,6 @@\n let(:calendar) { Business::Calendar.new(holidays: holidays) }\n subject { calendar.business_days_between(date_1, date_2) }\n \n-\n context \"starting on a business day\" do\n let(:date_1) { date_class.parse(\"Mon 2/6/2014\") }\n \n@@ -357,7 +356,6 @@\n let(:date_1) { date_class.parse(\"Sat 7/6/2014\") }\n \n context \"ending on a business day\" do\n-\n context \"including only business days & weekend days\" do\n let(:date_2) { date_class.parse(\"Mon 9/6/2014\") }\n it { is_expected.to eq(0) }\n@@ -393,7 +391,6 @@\n let(:date_1) { date_class.parse(\"Thu 12/6/2014\") }\n \n context \"ending on a business day\" do\n-\n context \"including only business days & holidays\" do\n let(:date_2) { date_class.parse(\"Fri 13/6/2014\") }\n it { is_expected.to eq(0) }\n@@ -462,4 +459,3 @@\n it_behaves_like \"common\"\n end\n end\n-" + } + ] +} diff --git a/nub/spec/fixtures/github/contents_js_nub.json b/nub/spec/fixtures/github/contents_js_nub.json new file mode 100644 index 00000000000..b959ab71795 --- /dev/null +++ b/nub/spec/fixtures/github/contents_js_nub.json @@ -0,0 +1,50 @@ +[ + { + "name": "nub.lock", + "path": "nub.lock", + "sha": "5b0a45fe1229f38af2dedd390b9c531458b07262", + "size": 102275, + "url": "https://api.github.com/repos/toddledev/toddle/contents/nub.lock?ref=main", + "html_url": "https://github.com/toddledev/toddle/blob/main/nub.lock", + "git_url": "https://api.github.com/repos/toddledev/toddle/git/blobs/5b0a45fe1229f38af2dedd390b9c531458b07262", + "download_url": "https://raw.githubusercontent.com/toddledev/toddle/main/nub.lock", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/toddledev/toddle/contents/nub.lock?ref=main", + "git": "https://api.github.com/repos/toddledev/toddle/git/blobs/5b0a45fe1229f38af2dedd390b9c531458b07262", + "html": "https://github.com/toddledev/toddle/blob/main/nub.lock" + } + }, + { + "name": "bunfig.toml", + "path": "bunfig.toml", + "sha": "d8bd900b81f2e7462aaa38a3bd592040f5e9ba78", + "size": 33, + "url": "https://api.github.com/repos/toddledev/toddle/contents/bunfig.toml?ref=main", + "html_url": "https://github.com/toddledev/toddle/blob/main/bunfig.toml", + "git_url": "https://api.github.com/repos/toddledev/toddle/git/blobs/d8bd900b81f2e7462aaa38a3bd592040f5e9ba78", + "download_url": "https://raw.githubusercontent.com/toddledev/toddle/main/bunfig.toml", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/toddledev/toddle/contents/bunfig.toml?ref=main", + "git": "https://api.github.com/repos/toddledev/toddle/git/blobs/d8bd900b81f2e7462aaa38a3bd592040f5e9ba78", + "html": "https://github.com/toddledev/toddle/blob/main/bunfig.toml" + } + }, + { + "name": "package.json", + "path": "package.json", + "sha": "1393fcaa2e31945e9599741fbf04ed271cb7de22", + "size": 1371, + "url": "https://api.github.com/repos/toddledev/toddle/contents/package.json?ref=main", + "html_url": "https://github.com/toddledev/toddle/blob/main/package.json", + "git_url": "https://api.github.com/repos/toddledev/toddle/git/blobs/1393fcaa2e31945e9599741fbf04ed271cb7de22", + "download_url": "https://raw.githubusercontent.com/toddledev/toddle/main/package.json", + "type": "file", + "_links": { + "self": "https://api.github.com/repos/toddledev/toddle/contents/package.json?ref=main", + "git": "https://api.github.com/repos/toddledev/toddle/git/blobs/1393fcaa2e31945e9599741fbf04ed271cb7de22", + "html": "https://github.com/toddledev/toddle/blob/main/package.json" + } + } +] diff --git a/nub/spec/fixtures/github/gemfile_content.json b/nub/spec/fixtures/github/gemfile_content.json new file mode 100644 index 00000000000..4a36b5b0dc3 --- /dev/null +++ b/nub/spec/fixtures/github/gemfile_content.json @@ -0,0 +1,18 @@ +{ + "name": "Gemfile", + "path": "Gemfile", + "sha": "dbce0c9e2e7efd19139c2c0aeb0110e837812c2f", + "size": 291, + "url": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master", + "html_url": "https://github.com/gocardless/bump/blob/master/Gemfile", + "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/dbce0c9e2e7efd19139c2c0aeb0110e837812c2f", + "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/Gemfile?token=ABF4KfGg6a7sE1n1i2rrhUvqAKRhIkPiks5WD8X5wA%3D%3D", + "type": "file", + "content": "c291cmNlICJodHRwczovL3J1YnlnZW1zLm9yZyIKCmdlbSAic2hvcnl1a2Vu\nIiwgIn4+IDIuMC4wIgpnZW0gImdlbW5hc2l1bS1wYXJzZXIiLCAifj4gMC4x\nLjkiCgpncm91cCA6ZGV2ZWxvcG1lbnQgZG8KICBnZW0gInJzcGVjIiwgIn4+\nIDMuMy4wIgogIGdlbSAicnNwZWMtaXRzIiwgIn4+IDEuMi4wIgogIGdlbSAi\nd2VibW9jayIsICJ+PiAxLjIxLjAiCiAgZ2VtICJvY3Rva2l0IiwgIn4+IDQu\nMS4xIgogIGdlbSAicHJpdXMiLCAifj4gMS4wLjAiCiAgZ2VtICJkb3RlbnYi\nLCByZXF1aXJlOiBmYWxzZQplbmQK\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master", + "git": "https://api.github.com/repos/gocardless/bump/git/blobs/dbce0c9e2e7efd19139c2c0aeb0110e837812c2f", + "html": "https://github.com/gocardless/bump/blob/master/Gemfile" + } +} diff --git a/nub/spec/fixtures/github/nub_lock_content.json b/nub/spec/fixtures/github/nub_lock_content.json new file mode 100644 index 00000000000..cad2d81eabd --- /dev/null +++ b/nub/spec/fixtures/github/nub_lock_content.json @@ -0,0 +1,6 @@ +{ + "name": "nub.lock", + "path": "nub.lock", + "content": "lockfileVersion: '9.0'\n\nimporters:\n\n .:\n dependencies:\n etag:\n specifier: ^1.0.0\n version: 1.8.1\n\npackages:\n\n etag@1.8.1:\n resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}\n engines: {node: '>= 0.6'}\n\nsnapshots:\n\n etag@1.8.1: {}\n", + "encoding": "utf-8" +} diff --git a/nub/spec/fixtures/github/package_json_content.json b/nub/spec/fixtures/github/package_json_content.json new file mode 100644 index 00000000000..c5f315250c3 --- /dev/null +++ b/nub/spec/fixtures/github/package_json_content.json @@ -0,0 +1,18 @@ +{ + "name": "package.json", + "path": "package.json", + "sha": "5c7b3419e0056515122b981f1566ebe22c208251", + "size": 594, + "url": "https://api.github.com/repos/gocardless/bump/contents/package.json?ref=master", + "html_url": "https://github.com/gocardless/bump/blob/master/package.json", + "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/5c7b3419e0056515122b981f1566ebe22c208251", + "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/package.json?token=ABMwe0apDiKCctWHnEHnszRBAebVHjQnks5WJWD9wA%3D%3D", + "type": "file", + "content": "ewogICJuYW1lIjogImJ1bXAtdGVzdCIsCiAgInZlcnNpb24iOiAiMC4wLjEi\nLAogICJkZXNjcmlwdGlvbiI6ICIiLAogICJtYWluIjogImluZGV4LmpzIiwK\nICAic2NyaXB0cyI6IHsKICAgICJ0ZXN0IjogImVjaG8gXCJFcnJvcjogbm8g\ndGVzdCBzcGVjaWZpZWRcIiAmJiBleGl0IDEiCiAgfSwKICAicmVwb3NpdG9y\neSI6IHsKICAgICJ0eXBlIjogImdpdCIsCiAgICAidXJsIjogImdpdCtodHRw\nczovL2dpdGh1Yi5jb20vZ29jYXJkbGVzcy9idW1wLXRlc3QuZ2l0IgogIH0s\nCiAgImF1dGhvciI6ICIiLAogICJsaWNlbnNlIjogIklTQyIsCiAgImJ1Z3Mi\nOiB7CiAgICAidXJsIjogImh0dHBzOi8vZ2l0aHViLmNvbS9nb2NhcmRsZXNz\nL2J1bXAtdGVzdC9pc3N1ZXMiCiAgfSwKICAiaG9tZXBhZ2UiOiAiaHR0cHM6\nLy9naXRodWIuY29tL2dvY2FyZGxlc3MvYnVtcC10ZXN0I3JlYWRtZSIsCiAg\nImRlcGVuZGVuY2llcyI6IHsKICAgICJsb2Rhc2giOiAiXjEuMy4xIiwKICAg\nICJjaGFsayI6ICIwLjQuMCIsCiAgICAic3RvcHdvcmRzIjogIjAuMC4xIgog\nIH0sCiAgImRldkRlcGVuZGVuY2llcyI6IHsKICAgICJldGFnIjogIl4xLjAu\nMCIKICB9Cn0K\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/gocardless/bump/contents/package.json?ref=master", + "git": "https://api.github.com/repos/gocardless/bump/git/blobs/5c7b3419e0056515122b981f1566ebe22c208251", + "html": "https://github.com/gocardless/bump/blob/master/package.json" + } +} diff --git a/nub/spec/fixtures/github/package_json_with_dependency_arrays.json b/nub/spec/fixtures/github/package_json_with_dependency_arrays.json new file mode 100644 index 00000000000..43bb91ffade --- /dev/null +++ b/nub/spec/fixtures/github/package_json_with_dependency_arrays.json @@ -0,0 +1,18 @@ +{ + "name": "package.json", + "path": "package.json", + "sha": "800e0a4da6567d3d452cad3b0193b8956b654652", + "size": 548, + "url": "https://api.github.com/repos/AMorgaut/html5-eventsource/contents/package.json?ref=master", + "html_url": "https://github.com/AMorgaut/html5-eventsource/blob/master/package.json", + "git_url": "https://api.github.com/repos/AMorgaut/html5-eventsource/git/blobs/800e0a4da6567d3d452cad3b0193b8956b654652", + "download_url": "https://raw.githubusercontent.com/AMorgaut/html5-eventsource/master/package.json", + "type": "file", + "content": "ewogICJuYW1lIjogImh0bWw1LWV2ZW50c291cmNlIiwKICAiZGVzY3JpcHRp\nb24iOiAiQW4gaW1wbGVtZW50YXRpb24gb2YgdGhlIHN0YW5kYXJkIEhUTUw1\nIEV2ZW50U291cmNlIGNsaWVudCBpbnRlcmZhY2UiLAogICJ2ZXJzaW9uIjog\nIjAuMS4wIiwKICAicmVwb3NpdG9yeSI6IHsKICAgICJ0eXBlIjogImdpdCIs\nCiAgICAidXJsIjogImdpdDovL2dpdGh1Yi5jb20vQU1vcmdhdXQvaHRtbDUt\nZXZlbnRzb3VyY2UuZ2l0IgogIH0sCiAgImF1dGhvciI6ICJBbGV4YW5kcmUg\nTW9yZ2F1dCA8QWxleGFuZHJlLk1vcmdhdXRAZ21haWwuY29tPiAoaHR0cDov\nL2dpdGh1Yi5jb20vQU1vcmdhdXQpIiwKICAibWFpbiI6ICIuL2h0bWw1LWV2\nZW50c291cmNlLmpzIiwKICAiZW5naW5lcyI6IHsKICAgICJub2RlIjogIioi\nLAogICAgIndha2FuZGEiOiAiKiIKICB9LAogICJkZXBlbmRlbmNpZXMiOiBb\nCiAgICAgIHsidzNjLWRvbWV2ZW50cyI6ICIwLjEuMCJ9LAogICAgICB7Incz\nYy1kb21jb3JlLWVycm9ycyI6ICIwLjEuMCJ9CiAgXSwKICAibGljZW5zZSI6\nICJNSVQiCn0=\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/AMorgaut/html5-eventsource/contents/package.json?ref=master", + "git": "https://api.github.com/repos/AMorgaut/html5-eventsource/git/blobs/800e0a4da6567d3d452cad3b0193b8956b654652", + "html": "https://github.com/AMorgaut/html5-eventsource/blob/master/package.json" + } +} diff --git a/nub/spec/fixtures/github/package_json_with_path_content.json b/nub/spec/fixtures/github/package_json_with_path_content.json new file mode 100644 index 00000000000..cf77d720cf3 --- /dev/null +++ b/nub/spec/fixtures/github/package_json_with_path_content.json @@ -0,0 +1,18 @@ +{ + "name": "package.json", + "path": "package.json", + "sha": "5c7b3419e0056515122b981f1566ebe22c208251", + "size": 594, + "url": "https://api.github.com/repos/gocardless/bump/contents/package.json?ref=master", + "html_url": "https://github.com/gocardless/bump/blob/master/package.json", + "git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/5c7b3419e0056515122b981f1566ebe22c208251", + "download_url": "https://raw.githubusercontent.com/gocardless/bump/master/package.json?token=ABMwe0apDiKCctWHnEHnszRBAebVHjQnks5WJWD9wA%3D%3D", + "type": "file", + "content": "ewogICJuYW1lIjogImJ1bXAtdGVzdCIsCiAgInZlcnNpb24iOiAiMC4wLjEi\nLAogICJkZXNjcmlwdGlvbiI6ICIiLAogICJtYWluIjogImluZGV4LmpzIiwK\nICAic2NyaXB0cyI6IHsKICAgICJ0ZXN0IjogImVjaG8gXCJFcnJvcjogbm8g\ndGVzdCBzcGVjaWZpZWRcIiAmJiBleGl0IDEiCiAgfSwKICAicmVwb3NpdG9y\neSI6IHsKICAgICJ0eXBlIjogImdpdCIsCiAgICAidXJsIjogImdpdCtodHRw\nczovL2dpdGh1Yi5jb20vZ29jYXJkbGVzcy9idW1wLXRlc3QuZ2l0IgogIH0s\nCiAgImF1dGhvciI6ICIiLAogICJsaWNlbnNlIjogIklTQyIsCiAgImJ1Z3Mi\nOiB7CiAgICAidXJsIjogImh0dHBzOi8vZ2l0aHViLmNvbS9nb2NhcmRsZXNz\nL2J1bXAtdGVzdC9pc3N1ZXMiCiAgfSwKICAiaG9tZXBhZ2UiOiAiaHR0cHM6\nLy9naXRodWIuY29tL2dvY2FyZGxlc3MvYnVtcC10ZXN0I3JlYWRtZSIsCiAg\nImRlcGVuZGVuY2llcyI6IHsKICAgICJsb2Rhc2giOiAiXjEuMy4xIiwKICAg\nICJjaGFsayI6ICIwLjQuMCIsCiAgICAic3RvcHdvcmRzIjogIjAuMC4xIgog\nIH0sCiAgImRldkRlcGVuZGVuY2llcyI6IHsKICAgICJldGFnIjogImZpbGU6\nLi9kZXBzL2V0YWciLAogICAgImNvcmRvdmEtcGx1Z2luLWdlb2xvY2F0aW9u\nIjogewogICAgICAiR0VPTE9DQVRJT05fVVNBR0VfREVTQ1JJUFRJT04iOiAi\nVG8gbG9jYXRlIHlvdSIKICAgIH0KICB9Cn0=\n", + "encoding": "base64", + "_links": { + "self": "https://api.github.com/repos/gocardless/bump/contents/package.json?ref=master", + "git": "https://api.github.com/repos/gocardless/bump/git/blobs/5c7b3419e0056515122b981f1566ebe22c208251", + "html": "https://github.com/gocardless/bump/blob/master/package.json" + } +} diff --git a/nub/spec/fixtures/npm_responses/200_with_invalid_json.json b/nub/spec/fixtures/npm_responses/200_with_invalid_json.json new file mode 100644 index 00000000000..9d16daade80 --- /dev/null +++ b/nub/spec/fixtures/npm_responses/200_with_invalid_json.json @@ -0,0 +1,3 @@ +JFrog Landing
    Namespace Pollution Mechanism
    Unleash awesomeness.Private packages, team management tools, and powerful integrations. Get started with npm Orgs »

    @babel/core

    7.2.2 + • undefinedundefinedPublicundefined • Published +undefinedundefined
    undefinedundefined
    undefined
    +
    +
    +

    + @babel/core +

    +
    +

    Babel compiler core.

    +
    +

    See our website + @babel/core for more information or the + issues associated with this package. +

    +

    + Install +

    +

    Using npm:

    +
    +
    +                
    + + npm install --save-dev @babel/core + +
    +
    +
    +

    or using yarn:

    +
    +
    +                
    + + yarn add @babel/core --dev + +
    +
    +
    +
    +
    +
    +

    Keywords

    + +
    undefined
    undefined
    undefined
    undefined

    install

    undefined

    + + + + + + + + + + + + npm i + @babel/core + +undefined

    undefined
    +
    +

    + + Downloads + + + + + weekly downloads +

    +
    + +

    6,368,339

    +
    +
    undefined
    undefined
    +

    version

    +

    7.2.2

    undefined
    undefined
    +

    license

    +

    MIT

    undefined
    undefined
    +

    homepage

    +

    + babeljs.io +

    undefined
    undefined
    +

    repository

    +

    + + + + Git + + + + + + github + +

    undefined
    undefined
    +

    last publish

    +

    + +

    undefined
    undefined
    +

    collaborators

    +undefined
    undefined
    + +Report a vulnerabilityundefined
    undefined
    undefined
    undefined
    undefinedundefined
    undefined
    undefined
    undefined
    undefinedundefinedundefinedundefinedundefinedundefined diff --git a/nub/spec/fixtures/npm_responses/chalk.json b/nub/spec/fixtures/npm_responses/chalk.json new file mode 100644 index 00000000000..ccd803c7634 --- /dev/null +++ b/nub/spec/fixtures/npm_responses/chalk.json @@ -0,0 +1 @@ +{"_id":"chalk","_rev":"1138-32ba671323684c7d50db04a12f6886c4","name":"chalk","description":"Terminal string styling done right","dist-tags":{"latest":"2.4.2","next":"3.0.0-beta.1"},"versions":{"0.1.0":{"name":"chalk","version":"0.1.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.1.0","dist":{"shasum":"69afbee2ffab5e0db239450767a6125cbea50fa2","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.1.0.tgz"},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.1.1":{"name":"chalk","version":"0.1.1","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.1.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.1.1","dist":{"shasum":"fe6d90ae2c270424720c87ed92d36490b7d36ea0","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.1.1.tgz"},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.2.0":{"name":"chalk","version":"0.2.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.2.0","dist":{"shasum":"47270e80edce0e219911af65479d17db525ff5db","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.2.0.tgz"},"_from":".","_npmVersion":"1.2.32","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.2.1":{"name":"chalk","version":"0.2.1","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.2.1","dist":{"shasum":"7613e1575145b21386483f7f485aa5ffa8cbd10c","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.2.1.tgz"},"_from":".","_npmVersion":"1.3.8","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.3.0":{"name":"chalk","version":"0.3.0","description":"Terminal string styling done right","keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"homepage":"https://github.com/sindresorhus/chalk","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"license":"MIT","author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"files":["chalk.js"],"main":"chalk","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk.git"},"scripts":{"test":"mocha"},"dependencies":{"has-color":"~0.1.0","ansi-styles":"~0.2.0"},"devDependencies":{"mocha":"~1.12.0"},"engines":{"node":">=0.8.0"},"_id":"chalk@0.3.0","dist":{"shasum":"1c98437737f1199ebcc1d4c48fd41b9f9c8e8f23","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.3.0.tgz"},"_from":".","_npmVersion":"1.3.10","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.4.0":{"name":"chalk","version":"0.4.0","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"author":{"name":"Sindre Sorhus","email":"sindresorhus@gmail.com","url":"http://sindresorhus.com"},"engines":{"node":">=0.8.0"},"scripts":{"test":"mocha"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"has-color":"~0.1.0","ansi-styles":"~1.0.0","strip-ansi":"~0.1.0"},"devDependencies":{"mocha":"~1.x"},"bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.4.0","dist":{"shasum":"5199a3ddcd0c1efe23bc08c1b027b06176e0c64f","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz"},"_from":".","_npmVersion":"1.3.17","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"directories":{}},"0.5.0":{"name":"chalk","version":"0.5.0","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^1.1.0","escape-string-regexp":"^1.0.0","has-ansi":"^0.1.0","strip-ansi":"^0.3.0","supports-color":"^0.2.0"},"devDependencies":{"matcha":"^0.5.0","mocha":"*"},"bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.5.0","_shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","_from":".","_npmVersion":"1.4.9","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"375dfccbc21c0a60a8b61bc5b78f3dc2a55c212f","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.5.0.tgz"},"directories":{}},"0.5.1":{"name":"chalk","version":"0.5.1","description":"Terminal string styling done right. Created because the `colors` module does some really horrible things.","license":"MIT","repository":{"type":"git","url":"git://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^1.1.0","escape-string-regexp":"^1.0.0","has-ansi":"^0.1.0","strip-ansi":"^0.3.0","supports-color":"^0.2.0"},"devDependencies":{"matcha":"^0.5.0","mocha":"*"},"gitHead":"994758f01293f1fdcf63282e9917cb9f2cfbdaac","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@0.5.1","_shasum":"663b3a648b68b55d04690d49167aa837858f2174","_from":".","_npmVersion":"1.4.14","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"663b3a648b68b55d04690d49167aa837858f2174","tarball":"https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz"},"directories":{}},"1.0.0":{"name":"chalk","version":"1.0.0","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"https://github.com/sindresorhus/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","ansi","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.0.1","escape-string-regexp":"^1.0.2","has-ansi":"^1.0.3","strip-ansi":"^2.0.1","supports-color":"^1.3.0"},"devDependencies":{"matcha":"^0.6.0","mocha":"*"},"gitHead":"8864d3563313ed15574a38dd5c9d5966080c46ce","bugs":{"url":"https://github.com/sindresorhus/chalk/issues"},"homepage":"https://github.com/sindresorhus/chalk","_id":"chalk@1.0.0","_shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","_from":".","_npmVersion":"2.5.1","_nodeVersion":"0.12.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"b3cf4ed0ff5397c99c75b8f679db2f52831f96dc","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.0.0.tgz"},"directories":{}},"1.1.0":{"name":"chalk","version":"1.1.0","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"https://github.com/chalk/chalk"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.1.0","escape-string-regexp":"^1.0.2","has-ansi":"^2.0.0","strip-ansi":"^3.0.0","supports-color":"^2.0.0"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3"},"gitHead":"e9bb6e6000b1c5d4508afabfdc85dd70f582f515","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk","_id":"chalk@1.1.0","_shasum":"09b453cec497a75520e4a60ae48214a8700e0921","_from":".","_npmVersion":"2.10.1","_nodeVersion":"0.12.4","_npmUser":{"name":"jbnicolai","email":"jappelman@xebia.com"},"dist":{"shasum":"09b453cec497a75520e4a60ae48214a8700e0921","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.0.tgz"},"directories":{}},"1.1.1":{"name":"chalk","version":"1.1.1","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"jbnicolai","email":"jappelman@xebia.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.1.0","escape-string-regexp":"^1.0.2","has-ansi":"^2.0.0","strip-ansi":"^3.0.0","supports-color":"^2.0.0"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"8b554e254e89c85c1fd04dcc444beeb15824e1a5","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.1","_shasum":"509afb67066e7499f7eb3535c77445772ae2d019","_from":".","_npmVersion":"2.13.5","_nodeVersion":"0.12.7","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"shasum":"509afb67066e7499f7eb3535c77445772ae2d019","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.1.tgz"},"directories":{}},"1.1.2":{"name":"chalk","version":"1.1.2","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.2.1","escape-string-regexp":"^1.0.2","supports-color":"^3.1.2"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^5.2.0","require-uncached":"^1.0.2","resolve-from":"^2.0.0","semver":"^5.1.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"a838948dcbf2674dd28adfbb78e791900ae741e9","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.2","_shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","_from":".","_npmVersion":"2.14.2","_nodeVersion":"0.10.32","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"53e9f9e7742f7edf23065c29c0219175a7869155","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.2.tgz"},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/chalk-1.1.2.tgz_1459207923607_0.6091341155115515"},"deprecated":"chalk@1.1.2 introduces breaking changes. Please use 1.1.3 or above.","directories":{}},"1.1.3":{"name":"chalk","version":"1.1.3","description":"Terminal string styling done right. Much color.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"maintainers":[{"name":"qix","email":"i.am.qix@gmail.com"},{"name":"sindresorhus","email":"sindresorhus@gmail.com"},{"name":"unicorn","email":"sindresorhus+unicorn@gmail.com"}],"engines":{"node":">=0.10.0"},"scripts":{"test":"xo && mocha","bench":"matcha benchmark.js","coverage":"nyc npm test && nyc report","coveralls":"nyc npm test && nyc report --reporter=text-lcov | coveralls"},"files":["index.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^2.2.1","escape-string-regexp":"^1.0.2","has-ansi":"^2.0.0","strip-ansi":"^3.0.0","supports-color":"^2.0.0"},"devDependencies":{"coveralls":"^2.11.2","matcha":"^0.6.0","mocha":"*","nyc":"^3.0.0","require-uncached":"^1.0.2","resolve-from":"^1.0.0","semver":"^4.3.3","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"0d8d8c204eb87a4038219131ad4d8369c9f59d24","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@1.1.3","_shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","_from":".","_npmVersion":"2.14.2","_nodeVersion":"0.10.32","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"shasum":"a8115c55e4a702fe4d150abd3872822a7e09fc98","tarball":"https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz"},"_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/chalk-1.1.3.tgz_1459210604109_0.3892582862172276"},"directories":{}},"2.0.0":{"name":"chalk","version":"2.0.0","description":"Terminal string styling done right. Much color","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"coveralls":"^2.11.2","import-fresh":"^2.0.0","matcha":"^0.7.0","mocha":"*","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"3fca6150e23439e783409f5c8f948f767c2ddc5a","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.0.0","_npmVersion":"5.0.0","_nodeVersion":"8.0.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-7jy/5E6bVCRhLlvznnsbVPjsARuVC9HDkBjUKVaOmUrhsp6P3ExUUcW09htM7/qieRH+D2lHVpNbuYh7GjVJ0g==","shasum":"c25c5b823fedff921aa5d83da3ecb5392e84e533","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.0.0.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.0.0.tgz_1498780161964_0.21432337583974004"},"directories":{}},"2.0.1":{"name":"chalk","version":"2.0.1","description":"Terminal string styling done right. Much color","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc mocha","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"coveralls":"^2.11.2","import-fresh":"^2.0.0","matcha":"^0.7.0","mocha":"*","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"5827081719944a2f903b52a88baeec1ec8581f82","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.0.1","_npmVersion":"5.0.0","_nodeVersion":"8.0.0","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==","shasum":"dbec49436d2ae15f536114e76d14656cdbc0f44d","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.0.1.tgz_1498793206623_0.8611406192649156"},"deprecated":"Please upgrade to Chalk 2.1.0 - template literals in this version (2.0.1) are quite buggy.","directories":{}},"2.1.0":{"name":"chalk","version":"2.1.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^2.11.2","execa":"^0.7.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^3.0.0","xo":"*"},"xo":{"envs":["node","mocha"]},"gitHead":"38f641a222d7ee0e607e4e5209d3931d2af1e409","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.1.0","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==","shasum":"ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.1.0.tgz_1502078203099_0.6595528507605195"},"directories":{}},"2.2.0":{"name":"chalk","version":"2.2.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"d86db88e778fa856f4d6f5f68c588750ca06b822","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.2.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-0BMM/2hG3ZaoPfR6F+h/oWpZtsh3b/s62TjSM6MGCJWEbJDN1acqCXvyhhZsDSVFklpebUoQ5O1kKC7lOzrn9g==","shasum":"477b3bf2f9b8fd5ca9e429747e37f724ee7af240","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.2.0.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.2.0.tgz_1508296541817_0.8590951061341912"},"directories":{}},"2.2.2":{"name":"chalk","version":"2.2.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"e1177ec3628f6d0d37489c1e1accd2c389a376a8","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.2.2","_npmVersion":"5.3.0","_nodeVersion":"8.2.1","_npmUser":{"name":"qix","email":"i.am.qix@gmail.com"},"dist":{"integrity":"sha512-LvixLAQ4MYhbf7hgL4o5PeK32gJKvVzDRiSNIApDofQvyhl8adgG2lJVXn4+ekQoK7HL9RF8lqxwerpe0x2pCw==","shasum":"4403f5cf18f35c05f51fbdf152bf588f956cf7cb","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.2.2.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.2.2.tgz_1508815246099_0.3707860491704196"},"directories":{}},"2.3.0":{"name":"chalk","version":"2.3.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.1.0","escape-string-regexp":"^1.0.5","supports-color":"^4.0.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.8.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"14e0aa97727019b22f0a003fdc631aeec5e2e24c","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.0","_npmVersion":"5.4.2","_nodeVersion":"8.7.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==","shasum":"b5ea48efc9c1793dccc9b4767c93914d3f2d52ba","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk-2.3.0.tgz_1508818375657_0.9021007190458477"},"directories":{}},"2.3.1":{"name":"chalk","version":"2.3.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.0","escape-string-regexp":"^1.0.5","supports-color":"^5.2.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"ae8a03f2c5c49896adeb3dd4ec5350e4ab9449a2","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.1","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==","shasum":"523fe2678aec7b04e8041909292fe8b17059b796","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz","fileCount":6,"unpackedSize":24721},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.3.1_1518355108425_0.3816906865374552"},"_hasShrinkwrap":false},"2.3.2":{"name":"chalk","version":"2.3.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"]},"gitHead":"84f27d4bd86f7f482a32652ae536cd996ad204bd","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.3.2","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==","shasum":"250dc96b07491bfd601e648d66ddf5f60c7a5c65","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz","fileCount":6,"unpackedSize":24713},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.3.2_1520012630405_0.9222977073145247"},"_hasShrinkwrap":false},"2.4.0":{"name":"chalk","version":"2.4.0","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"af8b3657e96a0a6ca5190fb0d0a1345797148320","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.0","_npmVersion":"5.6.0","_nodeVersion":"8.10.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==","shasum":"a060a297a6b57e15b61ca63ce84995daa0fe6e52","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz","fileCount":7,"unpackedSize":27005,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa1Xf3CRA9TVsSAnZWagAA1DcP/2EhxWse6mGwicTqM2U5\nQl2Xol74cFmd6b4nCGZnGycgatfJtyhb1YoH/vL3uNqGFrQGBwAr4GoZxhGd\n7kL0xKWnfhGHFeUe//fSCklj4Aff700RteXornlDFxbK5jVELyYcXfG5xJ5i\ncAIuPb9YYXltdaSfvVcg49qIPcjRfZm5Wz8WxTaUAyD5Ag4lpWKVTgWZsU+c\nEKRQHu+UmpX2OsudafT6GL3ak7GE2+ysH1b0HcYVuf1Wdf39un+E0MXDs58C\nTLCZSASN99/KCEpjh8aa4YdXVU3x0rdf50KdKDBUMF3b6HnSfWqOS+OWZRFZ\nC0jvk58j4vmXCVb2puQI8HIuZXBlNeS59GaN3hB3rz7JMgrQC/LXycOU1x+5\nuKEKupRkkVsSRyAEUdHqx6dwkcm+TVGPnXjUMdYREL9VkyY9eB7lBYTEzH9I\nZN9H3JXrjo/dGVmFL6q+L7lCxLFsl1p+UCMxubUE9XV6C/QN4mQmiwIAwn04\nhJH1RFIFTHszVEUnAJMZ6SqRRJes5iSedAMyiUYi+1S86uQenyUqtIJbHsNO\n7+G3Jnfdw9e1+YMvk53PSJcdtt5ayOx7ezc0HLS5HD9g3bXhMbbxTupHOSAv\nVCiEoaKAmjJK7nbStTqrX3xjz85K+lNHZdKkIzPWX5TkEg8KMSGK3LxfXG8B\n+CuC\r\n=orOi\r\n-----END PGP SIGNATURE-----\r\n"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.0_1523939317754_0.3039215958746819"},"_hasShrinkwrap":false},"2.4.1":{"name":"chalk","version":"2.4.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"files":["index.js","templates.js","types/index.d.ts","index.js.flow"],"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"48ba5b0b9beadcabd9fc406ac4d9337d8fa6b36d","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==","shasum":"18c49ab16a037b6eb0152cc83e3471338215b66e","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz","fileCount":7,"unpackedSize":26917,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJa4WCICRA9TVsSAnZWagAAhgwP/2M/ItinhR06BFhLMh91\nK/ru5t71NzSzoEvI2nh4W57Wk9cU1NOYi1cI17nUvICHCL4Vq9mjvU0hajTw\ncAYtM0Lwl+G4Hk4JtuiZITYj93QY3yLSJ8zkj95JznFbH0Zd9KkZrkoGukcG\nFY9at0cfNyhBmwi5sEDAFktcw7wThQ6Wy3iIttQ0N1M6Lf1XILg9Xyq6Id/W\nlz3TbkCt6AZCS1icmDPIiLdVQuD9SfpusIDsHm5/6FJPShwmQjUlM6Kdy7lx\n6M8uhcIknpxjfPTA6/aSBC4qgXnDhuPPi9xF657/81Mswz4Tb71KOf6UqLPi\n3zk1D5PF71ujWs3wmPll9TAVGnWuNzE+X/7GVIB4qCrib3SgvRzMhL0Wo95v\nzxTpNoD23hKYwofUyV3cTFh47YwkVoPtOStRAgdE87rx+v3VjbWSThQJc3V8\nHOsIeTjpQMwAr/d2DnasHKlps/q+gnGKqhBhcf11tAKn9C7PsAQ2l6+E4Erc\nfPKqDRC6TVG7ABdwOtyNonHhrJ2JLgYj8d4mHdtsMTtFsUTOQR/+Rx0V8HJS\n9gBLmPr3yc/yEedYW68wP5tPK2SfvFTzgMBw5v0+tgIxOjUunGxDUV4a1Bpp\npCBLN7iS77FLMiMonfcD2z/SsoB+Hb+7q5eT/gua3BIUNNZEdmgw9queXw+q\n7DFE\r\n=LSlF\r\n-----END PGP SIGNATURE-----\r\n"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"},{"email":"sindresorhus+unicorn@gmail.com","name":"unicorn"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.1_1524719751701_0.7780175911150953"},"_hasShrinkwrap":false},"2.4.2":{"name":"chalk","version":"2.4.2","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"engines":{"node":">=4"},"scripts":{"test":"xo && tsc --project types && flow --max-warnings=0 && nyc ava","bench":"matcha benchmark.js","coveralls":"nyc report --reporter=text-lcov | coveralls"},"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^3.2.1","escape-string-regexp":"^1.0.5","supports-color":"^5.3.0"},"devDependencies":{"ava":"*","coveralls":"^3.0.0","execa":"^0.9.0","flow-bin":"^0.68.0","import-fresh":"^2.0.0","matcha":"^0.7.0","nyc":"^11.0.2","resolve-from":"^4.0.0","typescript":"^2.5.3","xo":"*"},"types":"types/index.d.ts","xo":{"envs":["node","mocha"],"ignores":["test/_flow.js"]},"gitHead":"9776a2ae5b5b1712ccf16416b55f47e575a81fb9","bugs":{"url":"https://github.com/chalk/chalk/issues"},"homepage":"https://github.com/chalk/chalk#readme","_id":"chalk@2.4.2","_npmVersion":"6.5.0","_nodeVersion":"10.13.0","_npmUser":{"name":"sindresorhus","email":"sindresorhus@gmail.com"},"dist":{"integrity":"sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==","shasum":"cd42541677a54333cf541a49108c1432b44c9424","tarball":"https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz","fileCount":7,"unpackedSize":26924,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMNEwCRA9TVsSAnZWagAAmpUQAJgCZygaBX9qniyJ7YVF\nOXq9BNycBSnHyRd5YnaoO6HB7ejh/M4CYYGPqdSQ0OXEk1teNm7iPhGhocbW\n0eEcg0gsnVTgkUKx5p3o841VKydwy72FDgO9WJjKm2QC/mwuYHB9kI7zkq3h\nkakWBNGlKxbKNYX+7x04BXx1H8Fn1CSE//133uQnUWzM6NSXrUwpiZTzwtXi\nOybESujfKq6x6DxlYsTTScThCUodQQTslxIrdeS8PZxQL1RqCwnJSMHi81nI\nPR5BNVbAEYOsZuw88mNEtc6sHellN3ZFVlZwFDu4ZDskgoMiXZVv7Qp6AXbN\nCdsz1ej/OBFdwUfjS17igoHY3sO3+7o3IuFFaCXM4lkSE2zu79M2A7H0GL0R\nUcyfM1OC/nRcLgeEytIDBSOAgeN4tstswdyagFQ36jymeKUyz+q50ziBchey\nZnxPMGYDMKTx+me3TGpf3SbjiSstyZm8GLWPhRLbkjIDajFcFnq2HZXUu/LR\npdFJIWqnJihr9dxxiPSxddqZspb/Jo2mD2+ILNxROZB5+nzmlLnV/PsnnbxM\nPRN0iYDQt6NtXce/GOFMasLwtwidfHx8B4ybmObU3btbmg7V7Og++xpVg+h1\nQfACtop8sZyVN3l65vhonCmioqpSLQPeEkMvwGN6/7wi01BRi5VI4DdEtIet\nHcNL\r\n=DerQ\r\n-----END PGP SIGNATURE-----\r\n"},"maintainers":[{"email":"i.am.qix@gmail.com","name":"qix"},{"email":"sindresorhus@gmail.com","name":"sindresorhus"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/chalk_2.4.2_1546703152138_0.5501232329596948"},"_hasShrinkwrap":false},"3.0.0-beta.1":{"name":"chalk","version":"3.0.0-beta.1","description":"Terminal string styling done right","license":"MIT","repository":{"type":"git","url":"git+https://github.com/chalk/chalk.git"},"main":"source","engines":{"node":">=8"},"scripts":{"test":"xo && nyc ava && tsd","bench":"matcha benchmark.js"},"keywords":["color","colour","colors","terminal","console","cli","string","str","ansi","style","styles","tty","formatting","rgb","256","shell","xterm","log","logging","command-line","text"],"dependencies":{"ansi-styles":"^4.1.0","supports-color":"^7.1.0"},"devDependencies":{"ava":"^2.4.0","coveralls":"^3.0.5","execa":"^2.0.3","import-fresh":"^3.1.0","matcha":"^0.7.0","nyc":"^14.1.1","resolve-from":"^5.0.0","tsd":"^0.7.4","xo":"^0.25.3"},"xo":{"rules":{"unicorn/prefer-string-slice":"off","unicorn/prefer-includes":"off"}},"readme":"

    \n\t
    \n\t
    \n\t\"Chalk\"\n\t
    \n\t
    \n\t
    \n

    \n\n> Terminal string styling done right\n\n[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg)\n\n\n\n**This readme reflects the next major version that is currently in development. You probably want [the v2 readme](https://www.npmjs.com/package/chalk).**\n\n\n## Highlights\n\n- Expressive API\n- Highly performant\n- Ability to nest styles\n- [256/Truecolor color support](#256-and-truecolor-color-support)\n- Auto-detects color support\n- Doesn't extend `String.prototype`\n- Clean and focused\n- Actively maintained\n- [Used by ~46,000 packages](https://www.npmjs.com/browse/depended/chalk) as of October 1, 2019\n\n\n## Install\n\n```console\n$ npm install chalk\n```\n\n\n## Usage\n\n```js\nconst chalk = require('chalk');\n\nconsole.log(chalk.blue('Hello world!'));\n```\n\nChalk comes with an easy to use composable API where you just chain and nest the styles you want.\n\n```js\nconst chalk = require('chalk');\nconst log = console.log;\n\n// Combine styled and normal strings\nlog(chalk.blue('Hello') + ' World' + chalk.red('!'));\n\n// Compose multiple styles using the chainable API\nlog(chalk.blue.bgRed.bold('Hello world!'));\n\n// Pass in multiple arguments\nlog(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));\n\n// Nest styles\nlog(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));\n\n// Nest styles of the same type even (color, underline, background)\nlog(chalk.green(\n\t'I am a green line ' +\n\tchalk.blue.underline.bold('with a blue substring') +\n\t' that becomes green again!'\n));\n\n// ES2015 template literal\nlog(`\nCPU: ${chalk.red('90%')}\nRAM: ${chalk.green('40%')}\nDISK: ${chalk.yellow('70%')}\n`);\n\n// ES2015 tagged template literal\nlog(chalk`\nCPU: {red ${cpu.totalPercent}%}\nRAM: {green ${ram.used / ram.total * 100}%}\nDISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}\n`);\n\n// Use RGB colors in terminal emulators that support it.\nlog(chalk.keyword('orange')('Yay for orange colored text!'));\nlog(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));\nlog(chalk.hex('#DEADED').bold('Bold gray!'));\n```\n\nEasily define your own themes:\n\n```js\nconst chalk = require('chalk');\n\nconst error = chalk.bold.red;\nconst warning = chalk.keyword('orange');\n\nconsole.log(error('Error!'));\nconsole.log(warning('Warning!'));\n```\n\nTake advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):\n\n```js\nconst name = 'Sindre';\nconsole.log(chalk.green('Hello %s'), name);\n//=> 'Hello Sindre'\n```\n\n\n## API\n\n### chalk.`