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.5
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.5.6
Choose a head ref
  • 3 commits
  • 10 files changed
  • 3 contributors

Commits on Dec 9, 2022

  1. Copy the full SHA
    4e92e97 View commit details

Commits on Dec 10, 2022

  1. Copy the full SHA
    52627ce View commit details
  2. 16.5.6

    raineorshine committed Dec 10, 2022
    Copy the full SHA
    41100f9 View commit details
Showing with 257 additions and 172 deletions.
  1. +2 −2 package-lock.json
  2. +1 −1 package.json
  3. +68 −65 src/index.ts
  4. +0 −7 src/lib/PackageInfo.ts
  5. +8 −9 src/lib/doctor.ts
  6. +130 −77 src/lib/getAllPackages.ts
  7. +25 −0 src/lib/loadPackageInfoFromFile.ts
  8. +9 −0 src/types/PackageInfo.ts
  9. +4 −3 test/deep.test.ts
  10. +10 −8 test/getAllPackages.test.ts
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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "npm-check-updates",
"version": "16.5.5",
"version": "16.5.6",
"author": "Tomas Junnonen <tomas1@gmail.com>",
"license": "Apache-2.0",
"contributors": [
133 changes: 68 additions & 65 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ import packageManagers from './package-managers'
import { Index } from './types/IndexType'
import { Options } from './types/Options'
import { PackageFile } from './types/PackageFile'
import { PackageInfo } from './types/PackageInfo'
import { RunOptions } from './types/RunOptions'
import { VersionSpec } from './types/VersionSpec'

@@ -151,6 +152,71 @@ const npmInstall = async (
}
}

/** Runs the dependency upgrades. Loads the ncurc, finds the package file, and handles --deep. */
async function runUpgrades(options: Options, timeout?: NodeJS.Timeout): Promise<Index<string> | PackageFile | void> {
const [packageInfos, workspacePackages]: [PackageInfo[], string[]] = await getAllPackages(options)

const packageFilepaths: string[] = packageInfos.map((packageInfo: PackageInfo) => packageInfo.filepath)

// enable deep mode if --deep, --workspace, --workspaces, or if multiple package files are found
const isWorkspace = options.workspaces || !!options.workspace?.length
options.deep = options.deep || isWorkspace || packageInfos.length > 1

let analysis: Index<PackageFile> | PackageFile | void
if (options.global) {
const analysis = await runGlobal(options)
clearTimeout(timeout)
return analysis
} else if (options.deep) {
analysis = await packageInfos.reduce(async (previousPromise, packageInfo: PackageInfo) => {
const packages = await previousPromise
// copy object to prevent share .ncurc options between different packageFile, to prevent unpredictable behavior
const rcResult = await getNcuRc({ packageFile: packageInfo.filepath, color: options.color })
let rcConfig = rcResult && rcResult.config ? rcResult.config : {}
if (options.mergeConfig && Object.keys(rcConfig).length) {
// Merge config options.
rcConfig = mergeOptions(options, rcConfig)
}
const pkgOptions: Options = {
...options,
...rcConfig,
packageFile: packageInfo.filepath,
workspacePackages,
}
const [pkgData, pkgFile] = await findPackage(pkgOptions)
return {
...packages,
// index by relative path if cwd was specified
[pkgOptions.cwd
? path
.relative(path.resolve(pkgOptions.cwd), pkgFile!)
// convert Windows path to *nix path for consistency
.replace(/\\/g, '/')
: pkgFile!]: await runLocal(pkgOptions, pkgData, pkgFile),
}
}, Promise.resolve({} as Index<PackageFile> | PackageFile))
if (options.json) {
printJson(options, analysis)
}
} else {
// mutate packageFile when glob pattern finds only single package
if (packageInfos.length === 1 && packageInfos[0].filepath !== (options.packageFile || 'package.json')) {
options.packageFile = packageInfos[0].filepath
}
const [pkgData, pkgFile] = await findPackage(options)
analysis = await runLocal(options, pkgData, pkgFile)
}
clearTimeout(timeout)

// suggest install command or auto-install
if (options.upgrade) {
// if workspaces, install from root project folder
await npmInstall(isWorkspace ? ['package.json'] : packageFilepaths, analysis, options)
}

return analysis
}

/** Main entry point.
*
* @returns Promise<
@@ -181,7 +247,7 @@ export async function run(
options.prefix = await packageManagers[options.packageManager === 'yarn' ? 'yarn' : 'npm'].defaultPrefix!(options)
}

let timeout: NodeJS.Timeout
let timeout: NodeJS.Timeout | undefined
let timeoutPromise: Promise<void> = new Promise(() => null)
if (options.timeout) {
const timeoutMs = isString(options.timeout) ? Number.parseInt(options.timeout, 10) : options.timeout
@@ -199,69 +265,6 @@ export async function run(
})
}

/** Runs the dependency upgrades. Loads the ncurc, finds the package file, and handles --deep. */
async function runUpgrades(): Promise<Index<string> | PackageFile | void> {
const [pkgs, workspacePackages]: [string[], string[]] = await getAllPackages(options)

// enable deep mode if --deep, --workspace, --workspaces, or if multiple package files are found
const isWorkspace = options.workspaces || !!options.workspace?.length
options.deep = options.deep || isWorkspace || pkgs.length > 1

let analysis: Index<PackageFile> | PackageFile | void
if (options.global) {
const analysis = await runGlobal(options)
clearTimeout(timeout)
return analysis
} else if (options.deep) {
analysis = await pkgs.reduce(async (previousPromise, packageFile) => {
const packages = await previousPromise
// copy object to prevent share .ncurc options between different packageFile, to prevent unpredictable behavior
const rcResult = await getNcuRc({ packageFile, color: options.color })
let rcConfig = rcResult && rcResult.config ? rcResult.config : {}
if (options.mergeConfig && Object.keys(rcConfig).length) {
// Merge config options.
rcConfig = mergeOptions(options, rcConfig)
}
const pkgOptions: Options = {
...options,
...rcConfig,
packageFile,
workspacePackages,
}
const [pkgData, pkgFile] = await findPackage(pkgOptions)
return {
...packages,
// index by relative path if cwd was specified
[pkgOptions.cwd
? path
.relative(path.resolve(pkgOptions.cwd), pkgFile!)
// convert Windows path to *nix path for consistency
.replace(/\\/g, '/')
: pkgFile!]: await runLocal(pkgOptions, pkgData, pkgFile),
}
}, Promise.resolve({} as Index<PackageFile> | PackageFile))
if (options.json) {
printJson(options, analysis)
}
} else {
// mutate packageFile when glob pattern finds only single package
if (pkgs.length === 1 && pkgs[0] !== (options.packageFile || 'package.json')) {
options.packageFile = pkgs[0]
}
const [pkgData, pkgFile] = await findPackage(options)
analysis = await runLocal(options, pkgData, pkgFile)
}
clearTimeout(timeout)

// suggest install command or auto-install
if (options.upgrade) {
// if workspaces, install from root project folder
await npmInstall(isWorkspace ? ['package.json'] : pkgs, analysis, options)
}

return analysis
}

// doctor mode
if (options.doctor) {
// execute with -u
@@ -276,7 +279,7 @@ export async function run(
}
// normal mode
else {
return Promise.race([timeoutPromise, runUpgrades()])
return Promise.race([timeoutPromise, runUpgrades(options, timeout)])
}
}

7 changes: 0 additions & 7 deletions src/lib/PackageInfo.ts

This file was deleted.

17 changes: 8 additions & 9 deletions src/lib/doctor.ts
Original file line number Diff line number Diff line change
@@ -7,10 +7,11 @@ import spawnYarn from '../package-managers/yarn'
import { Index } from '../types/IndexType'
import { Options } from '../types/Options'
import { PackageFile } from '../types/PackageFile'
import { PackageInfo } from '../types/PackageInfo'
import { SpawnOptions } from '../types/SpawnOptions'
import { VersionSpec } from '../types/VersionSpec'
import { PackageInfo } from './PackageInfo'
import chalk, { chalkInit } from './chalk'
import loadPackageInfoFromFile from './loadPackageInfoFromFile'
import upgradePackageData from './upgradePackageData'

type Run = (options?: Options) => Promise<PackageFile | Index<VersionSpec> | void>
@@ -46,9 +47,7 @@ const npm = (
}

/** Load and validate package file and tests. */
const loadPackageFile = async (options: Options): Promise<PackageInfo> => {
let pkg: PackageFile, pkgFile: string

const loadPackageFileForDoctor = async (options: Options): Promise<PackageInfo> => {
// assert no --packageData or --packageFile
if (options.packageData || options.packageFile) {
console.error(
@@ -57,32 +56,32 @@ const loadPackageFile = async (options: Options): Promise<PackageInfo> => {
process.exit(1)
}

let packageInfo: PackageInfo
// assert package.json
try {
pkgFile = await fs.readFile('package.json', 'utf-8')
pkg = JSON.parse(pkgFile)
packageInfo = await loadPackageInfoFromFile('package.json')
} catch (e) {
console.error('Missing or invalid package.json')
process.exit(1)
}

// assert npm script "test" (unless a custom test script is specified)
if (!options.doctorTest && !pkg.scripts?.test) {
if (!options.doctorTest && !packageInfo.pkg.scripts?.test) {
console.error(
'No npm "test" script defined. You must define a "test" script in the "scripts" section of your package.json to use --doctor.',
)
process.exit(1)
}

return { pkg, pkgFile }
return packageInfo
}

/** Iteratively installs upgrades and runs tests to identify breaking upgrades. */
// we have to pass run directly since it would be a circular require if doctor included this file
const doctor = async (run: Run, options: Options): Promise<void> => {
await chalkInit()
const lockFileName = options.packageManager === 'yarn' ? 'yarn.lock' : 'package-lock.json'
const { pkg, pkgFile }: PackageInfo = await loadPackageFile(options)
const { pkg, pkgFile }: PackageInfo = await loadPackageFileForDoctor(options)

// flatten all deps into one so we can iterate over them
const allDependencies: Index<VersionSpec> = {
Loading