|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Creates a variant of package.json, hard-coded to use the oldest version of each dependency in |
| 3 | +# the supported range. |
| 4 | +# |
| 5 | +# package.json is taken from the current working directory. The script does not modify the file - |
| 6 | +# the new version is instead printed to the standard output. |
| 7 | +# |
| 8 | +# Dependencies: npm, jq, semver |
| 9 | + |
| 10 | +set -euo pipefail |
| 11 | + |
| 12 | +function fail { >&2 echo "$@"; exit 1; } |
| 13 | + |
| 14 | +function find_min_supported_versions { |
| 15 | + local packages_json min_versions packages supported_range available_versions min_version |
| 16 | + |
| 17 | + # The function expects a JSON dict with package names and versions, extracted from package.json by the caller. |
| 18 | + packages_json=$(cat -) |
| 19 | + |
| 20 | + # Use @tsv filter to get tab-separated package names. We assume that neither packages, nor |
| 21 | + # available versions contain spaces. Spaces in version range are fine though. |
| 22 | + packages=$(echo "$packages_json" | jq --raw-output 'keys | @tsv') |
| 23 | + min_versions=() |
| 24 | + for package in $packages; do |
| 25 | + available_versions=$(npm view "$package" versions --json | jq --raw-output @tsv) |
| 26 | + supported_range=$(echo "$packages_json" | jq --raw-output ".\"${package}\"") |
| 27 | + |
| 28 | + # shellcheck disable=SC2086 |
| 29 | + # semver prints versions matching the range, one per line, in semver order, oldest first |
| 30 | + min_version=$(semver $available_versions --range "$supported_range" | head --lines 1) |
| 31 | + [[ $min_version != "" ]] || fail "No version matching ${supported_range} found for package ${package}." |
| 32 | + |
| 33 | + # Debug info. It goes to stderr not to interfere with actual output. |
| 34 | + >&2 echo "Package ${package}:" |
| 35 | + >&2 echo " minimum version: ${min_version}" |
| 36 | + >&2 echo " supported range: ${supported_range}" |
| 37 | + >&2 echo " available versions: ${available_versions}" |
| 38 | + >&2 echo |
| 39 | + |
| 40 | + min_versions+=("{\"${package}\": \"${min_version}\"}") |
| 41 | + done |
| 42 | + |
| 43 | + # Actual output: min_versions merged into a single dict. |
| 44 | + echo "${min_versions[@]}" | jq --slurp add |
| 45 | +} |
| 46 | + |
| 47 | +dependencies=$(jq .dependencies package.json | find_min_supported_versions) |
| 48 | +dev_dependencies=$(jq .devDependencies package.json | find_min_supported_versions) |
| 49 | + |
| 50 | +# Print package.json with overwritten dependency versions |
| 51 | +cat <<EOF | jq --slurp '.[0] * .[1]' package.json - |
| 52 | +{ |
| 53 | + "dependencies": ${dependencies}, |
| 54 | + "devDependencies": ${dev_dependencies} |
| 55 | +} |
| 56 | +EOF |
0 commit comments