From 5861301a6c04f09d15c79b74e7f6bf596b74a8b4 Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Wed, 23 Feb 2022 15:10:16 +0100 Subject: [PATCH 1/9] wip - initial --- .ncurc.js | 10 ++++++++++ src/cli-options.ts | 6 ------ src/constants.ts | 6 ++++++ src/lib/initOptions.ts | 13 ++++++++----- src/lib/queryVersions.ts | 12 +++++++----- src/lib/runGlobal.ts | 2 +- src/lib/runLocal.ts | 2 +- src/logging.ts | 2 +- src/types.ts | 13 ++++--------- test/index.test.ts | 36 ++++++++++++++++++------------------ test/queryVersions.test.ts | 18 +++++++++--------- 11 files changed, 65 insertions(+), 55 deletions(-) diff --git a/.ncurc.js b/.ncurc.js index 29314b49..621fc964 100644 --- a/.ncurc.js +++ b/.ncurc.js @@ -1,4 +1,14 @@ module.exports = { + target: (name, versionRange) => { + let target = 'newest'; + if (versionRange?.startsWith('^')) { + target = 'minor'; + } else if (versionRange?.startsWith('~')) { + target = 'patch'; + } + console.log(' with', name, versionRange, target); + return target; + }, reject: [ // "If you use TypeScript, you will want to stay on Chalk 4 until TypeScript 4.6 is out." // https://github.com/microsoft/TypeScript/issues/46452 diff --git a/src/cli-options.ts b/src/cli-options.ts index 23dfbf5a..08d9c196 100644 --- a/src/cli-options.ts +++ b/src/cli-options.ts @@ -290,12 +290,6 @@ As a comparison: without using the --peer option, ncu will suggest the latest ve parse: s => parseInt(s, 10), default: 3, }, - { - long: 'semverLevel', - arg: 'value', - description: 'DEPRECATED. Renamed to --target.', - deprecated: true, - }, { long: 'silent', short: 's', diff --git a/src/constants.ts b/src/constants.ts index 734dc16d..a3c20e55 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,10 @@ +import { TargetFunction } from './types' + export const supportedVersionTargets = ['latest', 'newest', 'greatest', 'minor', 'patch'] +/** + * default fallback function that returns latest + */ +export const targetFallback: TargetFunction = () => 'latest' export const doctorHelpText = `Usage: ncu --doctor [-u] [options] diff --git a/src/lib/initOptions.ts b/src/lib/initOptions.ts index e5bd51f8..d47025fa 100644 --- a/src/lib/initOptions.ts +++ b/src/lib/initOptions.ts @@ -2,7 +2,7 @@ import _ from 'lodash' import fs from 'fs' import Chalk from 'chalk' import cliOptions from '../cli-options' -import { deepPatternPrefix } from '../constants' +import { deepPatternPrefix, targetFallback } from '../constants' import programError from './programError' import getPackageFileName from './getPackageFileName' import { print } from '../logging' @@ -76,11 +76,14 @@ function initOptions(runOptions: RunOptions, { cli }: { cli?: boolean } = {}): O programError(options, chalk.red(`Cannot specify both --packageFile and --deep. --deep is an alias for --packageFile '${deepPatternPrefix}package.json'`)) } - const target = options.newest ? 'newest' - : options.greatest ? 'greatest' - : options.target || options.semverLevel || 'latest' + const target = options.newest ? () => 'newest' + : options.greatest ? () => 'greatest' + : options.target || targetFallback - const autoPre = target === 'newest' || target === 'greatest' + console.log('target()', '' + target, target()) + + // include -alpha, -beta, -rc. + const autoPre = target() === 'newest' || target() === 'greatest' const format = [ ...options.format || [], diff --git a/src/lib/queryVersions.ts b/src/lib/queryVersions.ts index d605a288..6f614064 100644 --- a/src/lib/queryVersions.ts +++ b/src/lib/queryVersions.ts @@ -3,7 +3,7 @@ import cint from 'cint' import chalk from 'chalk' import pMap from 'p-map' import ProgressBar from 'progress' -import { supportedVersionTargets } from '../constants' +import { supportedVersionTargets, targetFallback } from '../constants' import getPackageManager from './getPackageManager' import packageManagers from '../package-managers' import { createNpmAlias, isGithubUrl, isPre, parseNpmAlias } from '../version-util' @@ -18,7 +18,7 @@ import { GetVersion, Index, Options, Version, VersionSpec } from '../types' */ async function queryVersions(packageMap: Index, options: Options = {}) { - const target = options.target || 'latest' + const target = options.target || targetFallback const packageList = Object.keys(packageMap) const packageManager = getPackageManager(options.packageManager) @@ -30,7 +30,7 @@ async function queryVersions(packageMap: Index, options: Options = // set the getPackageVersion function from options.target // TODO: Remove "as GetVersion" and fix types - const getPackageVersion = packageManager[target as keyof typeof packageManager] as GetVersion + const getPackageVersion = packageManager[target() as keyof typeof packageManager] as GetVersion if (!getPackageVersion) { const packageManagerSupportedVersionTargets = supportedVersionTargets.filter(t => t in packageManager) return Promise.reject(new Error(`Unsupported target "${target}" for ${options.packageManager || 'npm'}. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) @@ -55,11 +55,11 @@ async function queryVersions(packageMap: Index, options: Options = // override packageManager and getPackageVersion just for this dependency const packageManager = packageManagers.gitTags - const getPackageVersion = packageManager[target as keyof typeof packageManager] as GetVersion + const getPackageVersion = packageManager[target(name, version) as keyof typeof packageManager] as GetVersion if (!getPackageVersion) { const packageManagerSupportedVersionTargets = supportedVersionTargets.filter(t => t in packageManager) - return Promise.reject(new Error(`Unsupported target "${target}" for github urls. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) + return Promise.reject(new Error(`Unsupported target "${target(name, version)}" for github urls. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) } versionNew = await getPackageVersion(name, version, { ...options, @@ -71,6 +71,8 @@ async function queryVersions(packageMap: Index, options: Options = try { versionNew = await getPackageVersion(name, version, { ...options, + // @ts-expect-error TEMP + target: target(name, version), // upgrade prereleases to newer prereleases by default pre: options.pre != null ? options.pre : isPre(version), retry: options.retry ?? 2, diff --git a/src/lib/runGlobal.ts b/src/lib/runGlobal.ts index e2e35dee..559e81c3 100644 --- a/src/lib/runGlobal.ts +++ b/src/lib/runGlobal.ts @@ -19,7 +19,7 @@ async function runGlobal(options: Options): Promise|void> { print(options, 'globalPackages', 'silly') print(options, globalPackages, 'silly') print(options, '', 'silly') - print(options, `Fetching ${options.target} versions`, 'verbose') + print(options, `Fetching ${options.target?.()} versions`, 'verbose') const [upgraded, latest] = await upgradePackageDefinitions(globalPackages, options) print(options, latest, 'silly') diff --git a/src/lib/runLocal.ts b/src/lib/runLocal.ts index 92559021..4a65e013 100644 --- a/src/lib/runLocal.ts +++ b/src/lib/runLocal.ts @@ -74,7 +74,7 @@ async function runLocal(options: Options, pkgData?: Maybe, pkgFile?: May print(options, '\nCurrent:', 'verbose') print(options, current, 'verbose') - print(options, `\nFetching ${options.target} versions`, 'verbose') + print(options, `\nFetching ${options.target?.()} versions`, 'verbose') if (options.enginesNode) { options.nodeEngineVersion = _.get(pkg, 'engines.node') diff --git a/src/logging.ts b/src/logging.ts index 43a898d6..985dae8c 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -137,7 +137,7 @@ export function printUpgrades(options: Options, { current, latest, upgraded, num print(options, `All global packages are up-to-date ${smiley}`) } else { - print(options, `All dependencies match the ${options.target} package versions ${smiley}`) + print(options, `All dependencies match the ${options.target?.()} package versions ${smiley}`) } } else if (numUpgraded === 0 && total > 0) { diff --git a/src/types.ts b/src/types.ts index 54e5e299..e207811e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,6 +28,8 @@ export type VersionLevel = 'major' | 'minor' | 'patch' type FilterFunction = (packageName: string, version: SemVer[]) => boolean export type FilterRejectPattern = string | string[] | RegExp | RegExp[] | FilterFunction +export type TargetFunction = (name?: string, versionRange?: SemVer | string) => string + export interface Packument { name: string, deprecated?: boolean, @@ -274,22 +276,15 @@ export interface RunOptions { */ retry?: number, - /** - * DEPRECATED. Renamed to --target. - * - * @deprecated - */ - semverLevel?: string, - /** * Don't output anything (--loglevel silent). */ silent?: boolean, /** - * Target version to upgrade to: latest, newest, greatest, minor, patch. Run "ncu --help --target" for details.` (default: "latest") + * Target function that returns version to upgrade to: latest, newest, greatest, minor, patch. Run "ncu --help --target" for details.` (default: "latest") */ - target?: string, + target?: TargetFunction, /** * Global timeout in milliseconds. (default: no global timeout and 30 seconds per npm-registry-fetch). diff --git a/test/index.test.ts b/test/index.test.ts index f259c9a7..b68488d9 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -196,7 +196,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: 'newest' + target: () => 'newest' }).then(data => { return data!.should.eql({ dependencies: { @@ -215,7 +215,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: 'greatest' + target: () => 'greatest' }).then(data => { return data!.should.eql({ dependencies: { @@ -234,7 +234,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: 'newest', + target: () => 'newest', pre: false }).then(data => { return data!.should.eql({ @@ -249,7 +249,7 @@ describe('run', function () { return Promise.all([ ncu.run({ jsonAll: true, - target: 'newest', + target: () => 'newest', packageData: JSON.stringify({ dependencies: { del: '' @@ -258,7 +258,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: 'newest', + target: () => 'newest', packageData: JSON.stringify({ dependencies: { del: 'invalid range' @@ -267,7 +267,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: 'newest', + target: () => 'newest', packageData: JSON.stringify({ dependencies: { del: '*' @@ -276,7 +276,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: 'newest', + target: () => 'newest', packageData: JSON.stringify({ dependencies: { del: '~' @@ -318,59 +318,59 @@ describe('run', function () { describe('target', () => { it('do not allow --greatest and --newest together', async () => { - ncu.run({ greatest: true, target: 'newest' }) + ncu.run({ greatest: true, target: () => 'newest' }) .should.eventually.be.rejectedWith('Cannot specify both') - ncu.run({ target: 'greatest', newest: true }) + ncu.run({ target: () => 'greatest', newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') ncu.run({ greatest: true, newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not allow --target and --greatest together', async () => { - ncu.run({ target: 'greatest', greatest: true }) + ncu.run({ target: () => 'greatest', greatest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not allow --target and --newest together', async () => { - ncu.run({ target: 'newest', newest: true }) + ncu.run({ target: () => 'newest', newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not update major versions with --target minor', async () => { - const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) + const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) pkgData!.should.not.have.property('chalk') }) it('update minor versions with --target minor', async () => { - const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "2.3.0" } }' }) + const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "2.3.0" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('update patch versions with --target minor', async () => { - const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "2.4.0" } }' }) + const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "2.4.0" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('do not update major versions with --target patch', async () => { - const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) + const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) pkgData!.should.not.have.property('chalk') }) it('do not update minor versions with --target patch', async () => { - const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "2.3.2" } }' }) + const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "2.3.2" } }' }) pkgData!.should.not.have.property('chalk') }) it('update patch versions with --target patch', async () => { - const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "2.4.1" } }' }) + const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "2.4.1" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('skip non-semver versions with --target', async () => { - const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "test": "github:a/b" } }' }) + const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "test": "github:a/b" } }' }) pkgData!.should.not.have.property('test') }) diff --git a/test/queryVersions.test.ts b/test/queryVersions.test.ts index af0314bd..e66736fe 100644 --- a/test/queryVersions.test.ts +++ b/test/queryVersions.test.ts @@ -31,17 +31,17 @@ describe('queryVersions', function () { }) it('set the target explicitly to latest', () => { - return queryVersions({ async: '1.5.1' }, { target: 'latest', loglevel: 'silent' }) + return queryVersions({ async: '1.5.1' }, { target: () => 'latest', loglevel: 'silent' }) .should.eventually.have.property('async') }) it('set the target to greatest', () => { - return queryVersions({ async: '1.5.1' }, { target: 'greatest', loglevel: 'silent' }) + return queryVersions({ async: '1.5.1' }, { target: () => 'greatest', loglevel: 'silent' }) .should.eventually.have.property('async') }) it('return an error for an unsupported target', () => { - const a = queryVersions({ async: '1.5.1' }, { target: 'foo', loglevel: 'silent' }) + const a = queryVersions({ async: '1.5.1' }, { target: () => 'foo', loglevel: 'silent' }) return a.should.be.rejected }) @@ -143,7 +143,7 @@ describe('queryVersions', function () { it('github urls should support --target greatest', async () => { const upgrades = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: 'newest' }) + }, { loglevel: 'silent', target: () => 'newest' }) upgrades.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -153,7 +153,7 @@ describe('queryVersions', function () { it('github urls should support --target newest', async () => { const upgrades = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: 'newest' }) + }, { loglevel: 'silent', target: () => 'newest' }) upgrades.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -163,7 +163,7 @@ describe('queryVersions', function () { it('github urls should support --target minor', async () => { const upgrades = await queryVersions({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^0.1.0' - }, { loglevel: 'silent', target: 'minor' }) + }, { loglevel: 'silent', target: () => 'minor' }) upgrades.should.deep.equal({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^0.2.0' @@ -173,7 +173,7 @@ describe('queryVersions', function () { it('github urls should support --target patch', async () => { const upgrades = await queryVersions({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^1.0.0' - }, { loglevel: 'silent', target: 'patch' }) + }, { loglevel: 'silent', target: () => 'patch' }) upgrades.should.deep.equal({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^1.0.1' @@ -194,7 +194,7 @@ describe('queryVersions', function () { const upgradesNewest = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: 'newest' }) + }, { loglevel: 'silent', target: () => 'newest' }) upgradesNewest.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -202,7 +202,7 @@ describe('queryVersions', function () { const upgradesGreatest = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: 'greatest' }) + }, { loglevel: 'silent', target: () => 'greatest' }) upgradesGreatest.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' From eafe0d0178d6a956d6533c41a2e7b538873be82c Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Fri, 25 Feb 2022 11:05:45 +0100 Subject: [PATCH 2/9] revert test changes --- test/index.test.ts | 36 ++++++++++++++++++------------------ test/queryVersions.test.ts | 18 +++++++++--------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/test/index.test.ts b/test/index.test.ts index b68488d9..f259c9a7 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -196,7 +196,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: () => 'newest' + target: 'newest' }).then(data => { return data!.should.eql({ dependencies: { @@ -215,7 +215,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: () => 'greatest' + target: 'greatest' }).then(data => { return data!.should.eql({ dependencies: { @@ -234,7 +234,7 @@ describe('run', function () { 'ncu-mock-pre': '1.0.0' } }), - target: () => 'newest', + target: 'newest', pre: false }).then(data => { return data!.should.eql({ @@ -249,7 +249,7 @@ describe('run', function () { return Promise.all([ ncu.run({ jsonAll: true, - target: () => 'newest', + target: 'newest', packageData: JSON.stringify({ dependencies: { del: '' @@ -258,7 +258,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: () => 'newest', + target: 'newest', packageData: JSON.stringify({ dependencies: { del: 'invalid range' @@ -267,7 +267,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: () => 'newest', + target: 'newest', packageData: JSON.stringify({ dependencies: { del: '*' @@ -276,7 +276,7 @@ describe('run', function () { }), ncu.run({ jsonAll: true, - target: () => 'newest', + target: 'newest', packageData: JSON.stringify({ dependencies: { del: '~' @@ -318,59 +318,59 @@ describe('run', function () { describe('target', () => { it('do not allow --greatest and --newest together', async () => { - ncu.run({ greatest: true, target: () => 'newest' }) + ncu.run({ greatest: true, target: 'newest' }) .should.eventually.be.rejectedWith('Cannot specify both') - ncu.run({ target: () => 'greatest', newest: true }) + ncu.run({ target: 'greatest', newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') ncu.run({ greatest: true, newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not allow --target and --greatest together', async () => { - ncu.run({ target: () => 'greatest', greatest: true }) + ncu.run({ target: 'greatest', greatest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not allow --target and --newest together', async () => { - ncu.run({ target: () => 'newest', newest: true }) + ncu.run({ target: 'newest', newest: true }) .should.eventually.be.rejectedWith('Cannot specify both') }) it('do not update major versions with --target minor', async () => { - const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) + const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) pkgData!.should.not.have.property('chalk') }) it('update minor versions with --target minor', async () => { - const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "2.3.0" } }' }) + const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "2.3.0" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('update patch versions with --target minor', async () => { - const pkgData = await ncu.run({ target: () => 'minor', packageData: '{ "dependencies": { "chalk": "2.4.0" } }' }) + const pkgData = await ncu.run({ target: 'minor', packageData: '{ "dependencies": { "chalk": "2.4.0" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('do not update major versions with --target patch', async () => { - const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) + const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "3.0.0" } }' }) pkgData!.should.not.have.property('chalk') }) it('do not update minor versions with --target patch', async () => { - const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "2.3.2" } }' }) + const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "2.3.2" } }' }) pkgData!.should.not.have.property('chalk') }) it('update patch versions with --target patch', async () => { - const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "chalk": "2.4.1" } }' }) + const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "chalk": "2.4.1" } }' }) pkgData!.should.have.property('chalk') ;(pkgData as any).chalk.should.equal('2.4.2') }) it('skip non-semver versions with --target', async () => { - const pkgData = await ncu.run({ target: () => 'patch', packageData: '{ "dependencies": { "test": "github:a/b" } }' }) + const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "test": "github:a/b" } }' }) pkgData!.should.not.have.property('test') }) diff --git a/test/queryVersions.test.ts b/test/queryVersions.test.ts index e66736fe..af0314bd 100644 --- a/test/queryVersions.test.ts +++ b/test/queryVersions.test.ts @@ -31,17 +31,17 @@ describe('queryVersions', function () { }) it('set the target explicitly to latest', () => { - return queryVersions({ async: '1.5.1' }, { target: () => 'latest', loglevel: 'silent' }) + return queryVersions({ async: '1.5.1' }, { target: 'latest', loglevel: 'silent' }) .should.eventually.have.property('async') }) it('set the target to greatest', () => { - return queryVersions({ async: '1.5.1' }, { target: () => 'greatest', loglevel: 'silent' }) + return queryVersions({ async: '1.5.1' }, { target: 'greatest', loglevel: 'silent' }) .should.eventually.have.property('async') }) it('return an error for an unsupported target', () => { - const a = queryVersions({ async: '1.5.1' }, { target: () => 'foo', loglevel: 'silent' }) + const a = queryVersions({ async: '1.5.1' }, { target: 'foo', loglevel: 'silent' }) return a.should.be.rejected }) @@ -143,7 +143,7 @@ describe('queryVersions', function () { it('github urls should support --target greatest', async () => { const upgrades = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: () => 'newest' }) + }, { loglevel: 'silent', target: 'newest' }) upgrades.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -153,7 +153,7 @@ describe('queryVersions', function () { it('github urls should support --target newest', async () => { const upgrades = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: () => 'newest' }) + }, { loglevel: 'silent', target: 'newest' }) upgrades.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -163,7 +163,7 @@ describe('queryVersions', function () { it('github urls should support --target minor', async () => { const upgrades = await queryVersions({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^0.1.0' - }, { loglevel: 'silent', target: () => 'minor' }) + }, { loglevel: 'silent', target: 'minor' }) upgrades.should.deep.equal({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^0.2.0' @@ -173,7 +173,7 @@ describe('queryVersions', function () { it('github urls should support --target patch', async () => { const upgrades = await queryVersions({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^1.0.0' - }, { loglevel: 'silent', target: () => 'patch' }) + }, { loglevel: 'silent', target: 'patch' }) upgrades.should.deep.equal({ 'ncu-test-return-version': 'https://github.com/raineorshine/ncu-test-return-version#semver:^1.0.1' @@ -194,7 +194,7 @@ describe('queryVersions', function () { const upgradesNewest = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: () => 'newest' }) + }, { loglevel: 'silent', target: 'newest' }) upgradesNewest.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' @@ -202,7 +202,7 @@ describe('queryVersions', function () { const upgradesGreatest = await queryVersions({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^1.0.0' - }, { loglevel: 'silent', target: () => 'greatest' }) + }, { loglevel: 'silent', target: 'greatest' }) upgradesGreatest.should.deep.equal({ 'ncu-test-greatest-not-newest': 'https://github.com/raineorshine/ncu-test-greatest-not-newest#semver:^2.0.0-beta' From 5809b6f52479c2661719916d634b9f2e33bc4cd0 Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Fri, 25 Feb 2022 12:18:24 +0100 Subject: [PATCH 3/9] move getPackageVersion into scope with name and version --- src/constants.ts | 4 +--- src/lib/initOptions.ts | 4 ++-- src/lib/queryVersions.ts | 23 +++++++++++------------ src/lib/runGlobal.ts | 2 +- src/lib/runLocal.ts | 2 +- src/logging.ts | 2 +- src/types.ts | 5 +++-- test/index.test.ts | 21 ++++++++++++++++++++- 8 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index a3c20e55..b3297a3b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,10 +1,8 @@ -import { TargetFunction } from './types' - export const supportedVersionTargets = ['latest', 'newest', 'greatest', 'minor', 'patch'] /** * default fallback function that returns latest */ -export const targetFallback: TargetFunction = () => 'latest' +export const targetFallback = () => 'latest' export const doctorHelpText = `Usage: ncu --doctor [-u] [options] diff --git a/src/lib/initOptions.ts b/src/lib/initOptions.ts index d47025fa..32e758c2 100644 --- a/src/lib/initOptions.ts +++ b/src/lib/initOptions.ts @@ -80,10 +80,10 @@ function initOptions(runOptions: RunOptions, { cli }: { cli?: boolean } = {}): O : options.greatest ? () => 'greatest' : options.target || targetFallback - console.log('target()', '' + target, target()) + const targetResult = typeof target === 'string' ? target : targetFallback() // include -alpha, -beta, -rc. - const autoPre = target() === 'newest' || target() === 'greatest' + const autoPre = targetResult === 'newest' || targetResult === 'greatest' const format = [ ...options.format || [], diff --git a/src/lib/queryVersions.ts b/src/lib/queryVersions.ts index 6f614064..b39a17e2 100644 --- a/src/lib/queryVersions.ts +++ b/src/lib/queryVersions.ts @@ -28,14 +28,6 @@ async function queryVersions(packageMap: Index, options: Options = bar.render() } - // set the getPackageVersion function from options.target - // TODO: Remove "as GetVersion" and fix types - const getPackageVersion = packageManager[target() as keyof typeof packageManager] as GetVersion - if (!getPackageVersion) { - const packageManagerSupportedVersionTargets = supportedVersionTargets.filter(t => t in packageManager) - return Promise.reject(new Error(`Unsupported target "${target}" for ${options.packageManager || 'npm'}. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) - } - /** * Ignore 404 errors from getPackageVersion by having them return `null` * instead of rejecting. @@ -47,6 +39,7 @@ async function queryVersions(packageMap: Index, options: Options = const npmAlias = parseNpmAlias(packageMap[dep]) const [name, version] = npmAlias || [dep, packageMap[dep]] + const targetResult = typeof target === 'string' ? target : target(name, version) let versionNew: Version | null = null @@ -55,11 +48,11 @@ async function queryVersions(packageMap: Index, options: Options = // override packageManager and getPackageVersion just for this dependency const packageManager = packageManagers.gitTags - const getPackageVersion = packageManager[target(name, version) as keyof typeof packageManager] as GetVersion + const getPackageVersion = packageManager[targetResult as keyof typeof packageManager] as GetVersion if (!getPackageVersion) { const packageManagerSupportedVersionTargets = supportedVersionTargets.filter(t => t in packageManager) - return Promise.reject(new Error(`Unsupported target "${target(name, version)}" for github urls. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) + return Promise.reject(new Error(`Unsupported target "${targetResult}" for github urls. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) } versionNew = await getPackageVersion(name, version, { ...options, @@ -68,11 +61,17 @@ async function queryVersions(packageMap: Index, options: Options = }) } else { + // set the getPackageVersion function from options.target + // TODO: Remove "as GetVersion" and fix types + const getPackageVersion = packageManager[targetResult as keyof typeof packageManager] as GetVersion + if (!getPackageVersion) { + const packageManagerSupportedVersionTargets = supportedVersionTargets.filter(t => t in packageManager) + return Promise.reject(new Error(`Unsupported target "${targetResult}" for ${options.packageManager || 'npm'}. Supported version targets are: ${packageManagerSupportedVersionTargets.join(', ')}`)) + } + try { versionNew = await getPackageVersion(name, version, { ...options, - // @ts-expect-error TEMP - target: target(name, version), // upgrade prereleases to newer prereleases by default pre: options.pre != null ? options.pre : isPre(version), retry: options.retry ?? 2, diff --git a/src/lib/runGlobal.ts b/src/lib/runGlobal.ts index 559e81c3..e2e35dee 100644 --- a/src/lib/runGlobal.ts +++ b/src/lib/runGlobal.ts @@ -19,7 +19,7 @@ async function runGlobal(options: Options): Promise|void> { print(options, 'globalPackages', 'silly') print(options, globalPackages, 'silly') print(options, '', 'silly') - print(options, `Fetching ${options.target?.()} versions`, 'verbose') + print(options, `Fetching ${options.target} versions`, 'verbose') const [upgraded, latest] = await upgradePackageDefinitions(globalPackages, options) print(options, latest, 'silly') diff --git a/src/lib/runLocal.ts b/src/lib/runLocal.ts index 4a65e013..92559021 100644 --- a/src/lib/runLocal.ts +++ b/src/lib/runLocal.ts @@ -74,7 +74,7 @@ async function runLocal(options: Options, pkgData?: Maybe, pkgFile?: May print(options, '\nCurrent:', 'verbose') print(options, current, 'verbose') - print(options, `\nFetching ${options.target?.()} versions`, 'verbose') + print(options, `\nFetching ${options.target} versions`, 'verbose') if (options.enginesNode) { options.nodeEngineVersion = _.get(pkg, 'engines.node') diff --git a/src/logging.ts b/src/logging.ts index 985dae8c..43a898d6 100644 --- a/src/logging.ts +++ b/src/logging.ts @@ -137,7 +137,7 @@ export function printUpgrades(options: Options, { current, latest, upgraded, num print(options, `All global packages are up-to-date ${smiley}`) } else { - print(options, `All dependencies match the ${options.target?.()} package versions ${smiley}`) + print(options, `All dependencies match the ${options.target} package versions ${smiley}`) } } else if (numUpgraded === 0 && total > 0) { diff --git a/src/types.ts b/src/types.ts index e207811e..7b0098b7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,7 +28,8 @@ export type VersionLevel = 'major' | 'minor' | 'patch' type FilterFunction = (packageName: string, version: SemVer[]) => boolean export type FilterRejectPattern = string | string[] | RegExp | RegExp[] | FilterFunction -export type TargetFunction = (name?: string, versionRange?: SemVer | string) => string +export type TargetFunction = (name: string, versionRange: string) => string +export type Target = string | TargetFunction export interface Packument { name: string, @@ -284,7 +285,7 @@ export interface RunOptions { /** * Target function that returns version to upgrade to: latest, newest, greatest, minor, patch. Run "ncu --help --target" for details.` (default: "latest") */ - target?: TargetFunction, + target?: Target, /** * Global timeout in milliseconds. (default: no global timeout and 30 seconds per npm-registry-fetch). diff --git a/test/index.test.ts b/test/index.test.ts index f259c9a7..69eb18d0 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -4,6 +4,7 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import chaiString from 'chai-string' import * as ncu from '../src/' +import { TargetFunction } from '../src/types' chai.use(chaiAsPromised) chai.use(chaiString) @@ -369,11 +370,29 @@ describe('run', function () { ;(pkgData as any).chalk.should.equal('2.4.2') }) - it('skip non-semver versions with --target', async () => { + it('skip non-semver versions with --target patch', async () => { const pkgData = await ncu.run({ target: 'patch', packageData: '{ "dependencies": { "test": "github:a/b" } }' }) pkgData!.should.not.have.property('test') }) + it('custom target function to mimic semver', async () => { + // eslint-disable-next-line jsdoc/require-jsdoc + const target:TargetFunction = (name, versionRange) => versionRange?.startsWith('^') ? 'minor' : versionRange?.startsWith('~') ? 'patch' : 'latest' + const pkgData = await ncu.run({ + target, + packageData: JSON.stringify({ + dependencies: { + 'eslint-plugin-jsdoc': '~36.1.0', + mocha: '^8.3.2', + } + }) + }) + pkgData!.should.have.property('mocha') + ;(pkgData as any).mocha.should.equal('^8.4.0') + pkgData!.should.have.property('eslint-plugin-jsdoc') + ;(pkgData as any)['eslint-plugin-jsdoc'].should.equal('~36.1.1') + }) + }) // end 'target' describe('filterVersion', () => { From 7cbb88ed3031adf48d44035c897ec5e4341557b7 Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Fri, 25 Feb 2022 12:19:09 +0100 Subject: [PATCH 4/9] roll back changes on .ncurc.js --- .ncurc.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.ncurc.js b/.ncurc.js index 621fc964..29314b49 100644 --- a/.ncurc.js +++ b/.ncurc.js @@ -1,14 +1,4 @@ module.exports = { - target: (name, versionRange) => { - let target = 'newest'; - if (versionRange?.startsWith('^')) { - target = 'minor'; - } else if (versionRange?.startsWith('~')) { - target = 'patch'; - } - console.log(' with', name, versionRange, target); - return target; - }, reject: [ // "If you use TypeScript, you will want to stay on Chalk 4 until TypeScript 4.6 is out." // https://github.com/microsoft/TypeScript/issues/46452 From c7bacb50c9e1a09828c39192d99d79e96c4d3498 Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Fri, 25 Feb 2022 12:34:31 +0100 Subject: [PATCH 5/9] make diff smaller --- src/cli-options.ts | 6 ++++++ src/lib/initOptions.ts | 2 +- src/types.ts | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/cli-options.ts b/src/cli-options.ts index 08d9c196..23dfbf5a 100644 --- a/src/cli-options.ts +++ b/src/cli-options.ts @@ -290,6 +290,12 @@ As a comparison: without using the --peer option, ncu will suggest the latest ve parse: s => parseInt(s, 10), default: 3, }, + { + long: 'semverLevel', + arg: 'value', + description: 'DEPRECATED. Renamed to --target.', + deprecated: true, + }, { long: 'silent', short: 's', diff --git a/src/lib/initOptions.ts b/src/lib/initOptions.ts index 32e758c2..a639c4b0 100644 --- a/src/lib/initOptions.ts +++ b/src/lib/initOptions.ts @@ -78,7 +78,7 @@ function initOptions(runOptions: RunOptions, { cli }: { cli?: boolean } = {}): O const target = options.newest ? () => 'newest' : options.greatest ? () => 'greatest' - : options.target || targetFallback + : options.target || options.semverLevel || targetFallback const targetResult = typeof target === 'string' ? target : targetFallback() diff --git a/src/types.ts b/src/types.ts index 7b0098b7..fa5e24f7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -277,6 +277,13 @@ export interface RunOptions { */ retry?: number, + /** + * DEPRECATED. Renamed to --target. + * + * @deprecated + */ + semverLevel?: string, + /** * Don't output anything (--loglevel silent). */ From e4850b25077511f3645a2f912b3c035dfcffebdb Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Fri, 25 Feb 2022 12:39:05 +0100 Subject: [PATCH 6/9] revert initOptions since there is no benefit of using a function over a string by default --- src/constants.ts | 4 ---- src/lib/initOptions.ts | 13 +++++-------- src/lib/queryVersions.ts | 4 ++-- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index b3297a3b..734dc16d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,8 +1,4 @@ export const supportedVersionTargets = ['latest', 'newest', 'greatest', 'minor', 'patch'] -/** - * default fallback function that returns latest - */ -export const targetFallback = () => 'latest' export const doctorHelpText = `Usage: ncu --doctor [-u] [options] diff --git a/src/lib/initOptions.ts b/src/lib/initOptions.ts index a639c4b0..e5bd51f8 100644 --- a/src/lib/initOptions.ts +++ b/src/lib/initOptions.ts @@ -2,7 +2,7 @@ import _ from 'lodash' import fs from 'fs' import Chalk from 'chalk' import cliOptions from '../cli-options' -import { deepPatternPrefix, targetFallback } from '../constants' +import { deepPatternPrefix } from '../constants' import programError from './programError' import getPackageFileName from './getPackageFileName' import { print } from '../logging' @@ -76,14 +76,11 @@ function initOptions(runOptions: RunOptions, { cli }: { cli?: boolean } = {}): O programError(options, chalk.red(`Cannot specify both --packageFile and --deep. --deep is an alias for --packageFile '${deepPatternPrefix}package.json'`)) } - const target = options.newest ? () => 'newest' - : options.greatest ? () => 'greatest' - : options.target || options.semverLevel || targetFallback + const target = options.newest ? 'newest' + : options.greatest ? 'greatest' + : options.target || options.semverLevel || 'latest' - const targetResult = typeof target === 'string' ? target : targetFallback() - - // include -alpha, -beta, -rc. - const autoPre = targetResult === 'newest' || targetResult === 'greatest' + const autoPre = target === 'newest' || target === 'greatest' const format = [ ...options.format || [], diff --git a/src/lib/queryVersions.ts b/src/lib/queryVersions.ts index b39a17e2..5608ca60 100644 --- a/src/lib/queryVersions.ts +++ b/src/lib/queryVersions.ts @@ -3,7 +3,7 @@ import cint from 'cint' import chalk from 'chalk' import pMap from 'p-map' import ProgressBar from 'progress' -import { supportedVersionTargets, targetFallback } from '../constants' +import { supportedVersionTargets } from '../constants' import getPackageManager from './getPackageManager' import packageManagers from '../package-managers' import { createNpmAlias, isGithubUrl, isPre, parseNpmAlias } from '../version-util' @@ -18,7 +18,7 @@ import { GetVersion, Index, Options, Version, VersionSpec } from '../types' */ async function queryVersions(packageMap: Index, options: Options = {}) { - const target = options.target || targetFallback + const target = options.target || 'latest' const packageList = Object.keys(packageMap) const packageManager = getPackageManager(options.packageManager) From 6ddb46bb26d04ef587f7aaafaf476ce133c8c0fb Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Mon, 28 Feb 2022 11:17:23 +0100 Subject: [PATCH 7/9] parse version into Semver[] --- src/lib/queryVersions.ts | 3 ++- src/types.ts | 4 ++-- test/index.test.ts | 9 ++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/lib/queryVersions.ts b/src/lib/queryVersions.ts index 5608ca60..6c4c3381 100644 --- a/src/lib/queryVersions.ts +++ b/src/lib/queryVersions.ts @@ -3,6 +3,7 @@ import cint from 'cint' import chalk from 'chalk' import pMap from 'p-map' import ProgressBar from 'progress' +import { parseRange } from 'semver-utils' import { supportedVersionTargets } from '../constants' import getPackageManager from './getPackageManager' import packageManagers from '../package-managers' @@ -39,7 +40,7 @@ async function queryVersions(packageMap: Index, options: Options = const npmAlias = parseNpmAlias(packageMap[dep]) const [name, version] = npmAlias || [dep, packageMap[dep]] - const targetResult = typeof target === 'string' ? target : target(name, version) + const targetResult = typeof target === 'string' ? target : target(name, parseRange(version)) let versionNew: Version | null = null diff --git a/src/types.ts b/src/types.ts index fa5e24f7..610d40b5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,10 +25,10 @@ export type Version = string export type VersionSpec = string export type VersionLevel = 'major' | 'minor' | 'patch' -type FilterFunction = (packageName: string, version: SemVer[]) => boolean +type FilterFunction = (packageName: string, versionRange: SemVer[]) => boolean export type FilterRejectPattern = string | string[] | RegExp | RegExp[] | FilterFunction -export type TargetFunction = (name: string, versionRange: string) => string +export type TargetFunction = (packageName: string, versionRange: SemVer[]) => string export type Target = string | TargetFunction export interface Packument { diff --git a/test/index.test.ts b/test/index.test.ts index e360ddb9..32519196 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -378,20 +378,23 @@ describe('run', function () { it('custom target function to mimic semver', async () => { // eslint-disable-next-line jsdoc/require-jsdoc - const target:TargetFunction = (name, versionRange) => versionRange?.startsWith('^') ? 'minor' : versionRange?.startsWith('~') ? 'patch' : 'latest' + const target:TargetFunction = (name, [{ operator }]) => operator === '^' ? 'minor' : operator === '~' ? 'patch' : 'latest' const pkgData = await ncu.run({ target, packageData: JSON.stringify({ dependencies: { 'eslint-plugin-jsdoc': '~36.1.0', + juggernaut: '1.0.0', mocha: '^8.3.2', } }) }) - pkgData!.should.have.property('mocha') - ;(pkgData as any).mocha.should.equal('^8.4.0') pkgData!.should.have.property('eslint-plugin-jsdoc') ;(pkgData as any)['eslint-plugin-jsdoc'].should.equal('~36.1.1') + pkgData!.should.have.property('mocha') + ;(pkgData as any).mocha.should.equal('^8.4.0') + pkgData!.should.have.property('juggernaut') + ;(pkgData as any).juggernaut.should.equal('2.1.1') }) }) // end 'target' From 648f3fc7ee3bae21a15b676e362528426d530650 Mon Sep 17 00:00:00 2001 From: Jannis Hell Date: Mon, 28 Feb 2022 11:38:14 +0100 Subject: [PATCH 8/9] combine filter and target to true semver --- src/types.ts | 2 +- test/index.test.ts | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index 610d40b5..0fe8e429 100644 --- a/src/types.ts +++ b/src/types.ts @@ -25,7 +25,7 @@ export type Version = string export type VersionSpec = string export type VersionLevel = 'major' | 'minor' | 'patch' -type FilterFunction = (packageName: string, versionRange: SemVer[]) => boolean +export type FilterFunction = (packageName: string, versionRange: SemVer[]) => boolean export type FilterRejectPattern = string | string[] | RegExp | RegExp[] | FilterFunction export type TargetFunction = (packageName: string, versionRange: SemVer[]) => string diff --git a/test/index.test.ts b/test/index.test.ts index 32519196..550aeb0c 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -4,7 +4,7 @@ import chai from 'chai' import chaiAsPromised from 'chai-as-promised' import chaiString from 'chai-string' import * as ncu from '../src/' -import { TargetFunction } from '../src/types' +import { FilterFunction, TargetFunction } from '../src/types' chai.should() chai.use(chaiAsPromised) @@ -384,6 +384,7 @@ describe('run', function () { packageData: JSON.stringify({ dependencies: { 'eslint-plugin-jsdoc': '~36.1.0', + jsonlines: '0.1.0', juggernaut: '1.0.0', mocha: '^8.3.2', } @@ -391,10 +392,37 @@ describe('run', function () { }) pkgData!.should.have.property('eslint-plugin-jsdoc') ;(pkgData as any)['eslint-plugin-jsdoc'].should.equal('~36.1.1') - pkgData!.should.have.property('mocha') - ;(pkgData as any).mocha.should.equal('^8.4.0') + pkgData!.should.have.property('jsonlines') + ;(pkgData as any).jsonlines.should.equal('0.1.1') pkgData!.should.have.property('juggernaut') ;(pkgData as any).juggernaut.should.equal('2.1.1') + pkgData!.should.have.property('mocha') + ;(pkgData as any).mocha.should.equal('^8.4.0') + }) + + it('custom target and filter function to mimic semver', async () => { + // eslint-disable-next-line jsdoc/require-jsdoc + const target:TargetFunction = (name, [{ operator }]) => operator === '^' ? 'minor' : operator === '~' ? 'patch' : 'latest' + // eslint-disable-next-line jsdoc/require-jsdoc + const filter:FilterFunction = (_, [{ major, operator }]) => !(major === '0' || major === undefined || operator === undefined) + const pkgData = await ncu.run({ + filter, + target, + packageData: JSON.stringify({ + dependencies: { + 'eslint-plugin-jsdoc': '~36.1.0', + jsonlines: '0.1.0', + juggernaut: '1.0.0', + mocha: '^8.3.2', + } + }) + }) + pkgData!.should.have.property('eslint-plugin-jsdoc') + ;(pkgData as any)['eslint-plugin-jsdoc'].should.equal('~36.1.1') + pkgData!.should.not.have.property('jsonlines') + pkgData!.should.not.have.property('juggernaut') + pkgData!.should.have.property('mocha') + ;(pkgData as any).mocha.should.equal('^8.4.0') }) }) // end 'target' From 769bace49e1bfec57e60ead2cca5a01518c479b6 Mon Sep 17 00:00:00 2001 From: Raine Revere Date: Mon, 28 Feb 2022 09:19:43 -0700 Subject: [PATCH 9/9] Add custom target function instructions to cli-options. --- src/cli-options.ts | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/cli-options.ts b/src/cli-options.ts index 23dfbf5a..6dfe4c96 100644 --- a/src/cli-options.ts +++ b/src/cli-options.ts @@ -39,7 +39,24 @@ by each project's maintainers. Default.`]) other version numbers that are higher. Includes prereleases.`]) table.push(['patch', `Upgrade to the highest patch version without bumping the minor or major versions.`]) - return `Set the target version that is upgraded to (default: "latest").\n\n${table.toString()}` + return `Set the target version that is upgraded to (default: "latest"). + +${table.toString()} + +You can also specify a custom function in your .ncurc.js file, or when importing npm-check-updates: + + ${chalk.gray(`/** Custom target. + @param dependencyName The name of the dependency. + @param parsedVersion A parsed Semver object from semver-utils. + (See https://git.coolaj86.com/coolaj86/semver-utils.js#semverutils-parse-semverstring) + @returns One of the valid target values (specified in the table above). + */`)} + ${chalk.cyan('target')}: (dependencyName, [{ semver, version, operator, major, minor, patch, release, build }]) ${chalk.cyan('=>')} { + ${chalk.red('if')} (major ${chalk.red('===')} ${chalk.blue('0')}) ${chalk.red('return')} ${chalk.yellow('\'minor\'')} + ${chalk.red('return')} ${chalk.yellow('\'latest\'')} + } + +` } // store CLI options separately from bin file so that they can be used to build type definitions @@ -307,6 +324,7 @@ As a comparison: without using the --peer option, ncu will suggest the latest ve arg: 'value', description: 'Target version to upgrade to: latest, newest, greatest, minor, patch. Run "ncu --help --target" for details.` (default: "latest")', help: getHelpTargetTable(), + type: 'string | TargetFunction', }, { long: 'timeout',