Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: raineorshine/npm-check-updates
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v16.5.6
Choose a base ref
...
head repository: raineorshine/npm-check-updates
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v16.6.0
Choose a head ref
  • 6 commits
  • 13 files changed
  • 2 contributors

Commits on Dec 10, 2022

  1. Copy the full SHA
    76b85df View commit details
  2. Copy the full SHA
    487a2f6 View commit details

Commits on Dec 11, 2022

  1. Copy the full SHA
    c42b5b5 View commit details
  2. chore(type): specify that programError() never returns, aiding typing

    This extra type spec means we don't have to add 'undefined' to functions
    that don't explicitly return when calling programError()
    doublethefish authored and raineorshine committed Dec 11, 2022
    Copy the full SHA
    7d0d266 View commit details

Commits on Dec 14, 2022

  1. Copy the full SHA
    a668ef6 View commit details
  2. 16.6.0

    raineorshine committed Dec 14, 2022
    Copy the full SHA
    813b287 View commit details
32 changes: 28 additions & 4 deletions .husky/post-commit
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

SHORT_SHA=$(git rev-parse HEAD)
LINT_LOG="$TMPDIR"/ncu.lint."$SHORT_SHA".log

# display a notification
# if osascript is not supported, do nothing
notify() {
# if osascript is not supported, do nothing
if [ -f /usr/bin/osascript ]; then
/usr/bin/osascript -e "display notification \"$*\" with title \"Notification\""
# get '<SHORT_SHA> <FIRST_LINE_OF_COMMIT_MSG>'
COMMIT_INFO=$(git log --oneline -n 1 --format="%h %s")

# read back in the lint errors
# TODO: update for each tye of error
ERRORS=$(cat "$LINT_LOG" | sed 1,4d)

# Trigger apple- or OSA-script on supported platforms
/usr/bin/osascript -e "display notification \"$ERRORS\" with title \"ncu: $COMMIT_INFO: $*\""
fi

# always clean up the lint output, and do not clag-up TMPDIR
rm "$LINT_LOG"
}

# ensure failed lint exit code passes through sed
set -o pipefail

# omit first 4 lines printed by npm run
npm run lint:src 2>&1 | sed 1,4d || notify "Lint Error" &
branch=$(git branch --show-current)
# Do NOT run this when rebasing or we can't get the branch
if [ -z "$branch" ]; then
exit 0
fi

# Lint asynchrously, not blocking the terminal and piping all output to a file.
# IFF lint fails trigger a pop-up (on supported platforms) with at least the
# first error shown.
# We pipe output so that the terminal (tmux, vim, emacs etc.) isn't borked by
# stray output.
npm run lint:src &> "$LINT_LOG" || notify "Lint Error" &
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "npm-check-updates",
"version": "16.5.6",
"version": "16.6.0",
"author": "Tomas Junnonen <tomas1@gmail.com>",
"license": "Apache-2.0",
"contributors": [
@@ -37,10 +37,8 @@
"prepare": "husky install",
"prepublishOnly": "npm run build",
"prettier": "prettier .",
"test": "npm run test:src && npm run test:timeout",
"test:src": "mocha test test/package-managers/npm test/package-managers/yarn test/package-managers/staticRegistry",
"test:src:cov": "npm run c8 npm run test:src",
"test:timeout": "mocha --exit test/timeout",
"test": "mocha test test/package-managers/npm test/package-managers/yarn test/package-managers/staticRegistry",
"test:cov": "npm run c8 npm run test",
"ncu": "node build/src/bin/cli.js"
},
"bin": {
@@ -163,7 +161,7 @@
"source-map-support/register",
"ts-node/register"
],
"timeout": 30000,
"timeout": 60000,
"trace-deprecation": true,
"trace-warnings": true,
"use_strict": true
2 changes: 1 addition & 1 deletion src/cli-options.ts
Original file line number Diff line number Diff line change
@@ -375,7 +375,7 @@ const cliOptions: CLIOption[] = [
long: 'dep',
arg: 'value',
description:
'Check one or more sections of dependencies only: dev, optional, peer, prod, bundle (comma-delimited).',
'Check one or more sections of dependencies only: dev, optional, peer, prod, bundle, packageManager (comma-delimited).',
default: ['prod', 'dev', 'bundle', 'optional'],
parse: value => (value && typeof value === 'string' ? value.split(',') : value),
type: 'string | string[]',
23 changes: 18 additions & 5 deletions src/lib/getCurrentDependencies.ts
Original file line number Diff line number Diff line change
@@ -15,6 +15,12 @@ const isGreaterThanSafe = (spec1: VersionSpec, spec2: VersionSpec) =>
// otherwise return true if spec2 is smaller than spec1
semver.gt(semver.minVersion(spec1)!, semver.minVersion(spec2)!)

/** Parses the packageManager field into a { [name]: version } pair. */
const parsePackageManager = (pkgData: PackageFile) => {
if (!pkgData.packageManager) return {}
const [name, version] = pkgData.packageManager.split('@')
return { [name]: version }
}
/**
* Get the current dependencies from the package file.
*
@@ -34,18 +40,25 @@ function getCurrentDependencies(pkgData: PackageFile = {}, options: Options = {}

// map the dependency section option to a full dependency section name
const depSections = depOptions.map(
short => (short === 'prod' ? 'dependencies' : short + 'Dependencies') as keyof PackageFile,
short =>
(short === 'prod'
? 'dependencies'
: short === 'packageManager'
? short
: short + 'Dependencies') as keyof PackageFile,
)

// get all dependencies from the selected sections
// if a dependency appears in more than one section, take the lowest version number
const allDependencies = depSections.reduce((accum, depSection) => {
return {
...accum,
...filterObject(
(pkgData[depSection] as Index<string>) || {},
(dep, spec) => !isGreaterThanSafe(spec, accum[dep]),
),
...(depSection === 'packageManager'
? parsePackageManager(pkgData)
: filterObject(
(pkgData[depSection] as Index<string>) || {},
(dep, spec) => !isGreaterThanSafe(spec, accum[dep]),
)),
}
}, {} as Index<VersionSpec>)

2 changes: 1 addition & 1 deletion src/lib/programError.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import { print } from '../lib/logging'
import { Options } from '../types/Options'

/** Print an error. Exit the process if in CLI mode. */
function programError(options: Options, message: string) {
function programError(options: Options, message: string): never {
if (options.cli) {
print(options, message, null, 'error')
process.exit(1)
23 changes: 21 additions & 2 deletions src/lib/upgradePackageData.ts
Original file line number Diff line number Diff line change
@@ -31,13 +31,19 @@ async function upgradePackageData(
: options.dep
: ['prod', 'dev', 'bundle', 'optional']

// map the dependency section option to a full dependency section name
const depSections = depOptions.map(
short => (short === 'prod' ? 'dependencies' : short + 'Dependencies') as keyof PackageFile,
short =>
(short === 'prod'
? 'dependencies'
: short === 'packageManager'
? short
: short + 'Dependencies') as keyof PackageFile,
)

// iterate through each dependency section
const sectionRegExp = new RegExp(`"(${depSections.join(`|`)})"s*:[^}]*`, 'g')
const newPkgData = pkgData.replace(sectionRegExp, section => {
let newPkgData = pkgData.replace(sectionRegExp, section => {
// replace each upgraded dependency in the section
Object.keys(upgraded).forEach(dep => {
const expression = `"${dep}"\\s*:\\s*"(${escapeRegexp(current[dep])})"`
@@ -48,6 +54,19 @@ async function upgradePackageData(
return section
})

if (depOptions.includes('packageManager')) {
const pkg = JSON.parse(pkgData) as PackageFile
if (pkg.packageManager) {
const [name] = pkg.packageManager.split('@')
if (upgraded[name]) {
newPkgData = newPkgData.replace(
/"packageManager"\s*:\s*".*?@[^"]*"/,
`"packageManager": "${name}@${upgraded[name]}"`,
)
}
}
}

return newPkgData
}

2 changes: 2 additions & 0 deletions src/types/PackageFile.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@ export interface PackageFile {
devDependencies?: Index<VersionSpec>
engines?: Index<VersionSpec>
name?: string
// https://nodejs.org/api/packages.html#packagemanager
packageManager?: string
optionalDependencies?: Index<VersionSpec>
peerDependencies?: Index<VersionSpec>
repository?: string | PackageFileRepository
14 changes: 0 additions & 14 deletions test/bin.test.ts
Original file line number Diff line number Diff line change
@@ -252,20 +252,6 @@ describe('reject', () => {
})
})

describe('with timeout option', () => {
it('exit with error when timeout exceeded', async () => {
return spawn(
'node',
[bin, '--timeout', '1'],
'{ "dependencies": { "express": "1" } }',
).should.eventually.be.rejectedWith('Exceeded global timeout of 1ms')
})

it('completes successfully with timeout', async () => {
return spawn('node', [bin, '--timeout', '100000'], '{ "dependencies": { "express": "1" } }')
})
})

describe('embedded versions', () => {
it('strip url from Github url in "to" output', async () => {
// use dynamic import for ESM module
Loading