Skip to content

Instantly share code, notes, and snippets.

@ttonyh
Forked from vividn/npmTimeMachine
Created December 8, 2021 13:18
Show Gist options
  • Save ttonyh/40ebf37b4475c093cc9bab2aa5db99cd to your computer and use it in GitHub Desktop.
Save ttonyh/40ebf37b4475c093cc9bab2aa5db99cd to your computer and use it in GitHub Desktop.
npmTimeMachine
#!/usr/bin/env bash
# npmTimeMachine
# Quickly get package versions where they would have been on a certain date
# Can be useful for getting out of dependency hell by slowly working your way forward in time
# as if you had stayed up to date in the first place.
#
# The script will run and find the appropriate package versions based on public npm publish data
#
# Usage:
# Go to the directory with the package.json and run
# `npmTimeMachine <date>`
# After running it will output <date>_dependencies.json
# Check through this file and then copy into your package.json
# Sweet salvation from the dependency hell :)
#
# MIT License
#
# Copyright (c) 2021 Nate Faber for Artory, Inc
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
set -euo pipefail
upgradeDate=$(date -d "$1" '+%Y-%m-%d')
upgradeDateEod="${upgradeDate}T23:59:59.999Z"
shift 1
fileout="./${upgradeDate}_dependencies.json"
tmpfile=$(mktemp)
function finish() {
rm "$tmpfile"
}
trap finish EXIT
echo "{" | tee "$tmpfile"
function calculate() {
case "$1" in
deps)
depList="$(jq -r '.dependencies | keys | .[]' package.json)"
depVersions=$(jq -r '.dependencies' package.json)
;;
devDeps)
depList="$(jq -r '.devDependencies | keys | .[]' package.json)"
depVersions=$(jq -r '.devDependencies' package.json)
;;
*)
echo "bad calculate option"
return 1
;;
esac
firstValue=true
for dep in $depList; do
currentVersion=$(jq -r '."'"$dep"'"' <<<"$depVersions")
# Comma work-around for valid JSON
if [[ -z $firstValue ]]; then
echo "," | tee -a "$tmpfile"
fi
firstValue=
# Some packages (custom links for example) don't have npm, just ignore and continue
set +e
if ! (npm view "$dep" time >/dev/null 2>&1); then
set -e
echo -en "\"$dep\": \"$currentVersion\"" | tee -a "$tmpfile"
continue
fi
set -e
# Get versions that were published on or before a date, and filter out versions with strings in the names (removes beta, experimental, etc)
version=$(npm view "$dep" time --json | jq -r '
[del(.created, .modified) |
to_entries[] |
select(.value<="'"$upgradeDateEod"'") |
select(.key|test("^[0-9.]+$")).key] |
last')
# Add the preexisting upgrade policy to the new version
if [ "${currentVersion:0:1}" = '^' ]; then
initialSymbol="^"
elif [ "${currentVersion:0:1}" = '~' ]; then
initialSymbol="~"
else
initialSymbol=
fi
echo -en "\"${dep}\": \"${initialSymbol}${version}\"" | tee -a "$tmpfile"
done
}
echo '"dependencies": {' | tee -a "$tmpfile"
calculate deps
echo -e "\n}," | tee -a "$tmpfile"
echo '"devDependencies": {' | tee -a "$tmpfile"
calculate devDeps
echo -e "\n}" | tee -a "$tmpfile"
echo "}" | tee -a "$tmpfile"
# Pass through jq for formatting and verification of proper json
jq . "$tmpfile" >"$fileout"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment