Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Target as a function #1052

Merged
merged 10 commits into from
Feb 28, 2022
10 changes: 10 additions & 0 deletions .ncurc.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 0 additions & 6 deletions src/cli-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
6 changes: 6 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -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]

Expand Down
13 changes: 8 additions & 5 deletions src/lib/initOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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 || [],
Expand Down
12 changes: 7 additions & 5 deletions src/lib/queryVersions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -18,7 +18,7 @@ import { GetVersion, Index, Options, Version, VersionSpec } from '../types'
*/
async function queryVersions(packageMap: Index<VersionSpec>, options: Options = {}) {

const target = options.target || 'latest'
const target = options.target || targetFallback
const packageList = Object.keys(packageMap)
const packageManager = getPackageManager(options.packageManager)

Expand All @@ -30,7 +30,7 @@ async function queryVersions(packageMap: Index<VersionSpec>, 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
Primajin marked this conversation as resolved.
Show resolved Hide resolved
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(', ')}`))
Expand All @@ -55,11 +55,11 @@ async function queryVersions(packageMap: Index<VersionSpec>, 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,
Expand All @@ -71,6 +71,8 @@ async function queryVersions(packageMap: Index<VersionSpec>, 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,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/runGlobal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async function runGlobal(options: Options): Promise<Index<string>|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')
Expand Down
2 changes: 1 addition & 1 deletion src/lib/runLocal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async function runLocal(options: Options, pkgData?: Maybe<string>, 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')
Expand Down
2 changes: 1 addition & 1 deletion src/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
13 changes: 4 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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).
Expand Down
36 changes: 18 additions & 18 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ describe('run', function () {
'ncu-mock-pre': '1.0.0'
}
}),
target: 'newest'
target: () => 'newest'
Primajin marked this conversation as resolved.
Show resolved Hide resolved
}).then(data => {
return data!.should.eql({
dependencies: {
Expand All @@ -215,7 +215,7 @@ describe('run', function () {
'ncu-mock-pre': '1.0.0'
}
}),
target: 'greatest'
target: () => 'greatest'
}).then(data => {
return data!.should.eql({
dependencies: {
Expand All @@ -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({
Expand All @@ -249,7 +249,7 @@ describe('run', function () {
return Promise.all([
ncu.run({
jsonAll: true,
target: 'newest',
target: () => 'newest',
packageData: JSON.stringify({
dependencies: {
del: ''
Expand All @@ -258,7 +258,7 @@ describe('run', function () {
}),
ncu.run({
jsonAll: true,
target: 'newest',
target: () => 'newest',
packageData: JSON.stringify({
dependencies: {
del: 'invalid range'
Expand All @@ -267,7 +267,7 @@ describe('run', function () {
}),
ncu.run({
jsonAll: true,
target: 'newest',
target: () => 'newest',
packageData: JSON.stringify({
dependencies: {
del: '*'
Expand All @@ -276,7 +276,7 @@ describe('run', function () {
}),
ncu.run({
jsonAll: true,
target: 'newest',
target: () => 'newest',
packageData: JSON.stringify({
dependencies: {
del: '~'
Expand Down Expand Up @@ -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')
})

Expand Down
18 changes: 9 additions & 9 deletions test/queryVersions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
})

Expand Down Expand Up @@ -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'
Expand All @@ -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'
Expand All @@ -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'
Expand All @@ -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'
Expand All @@ -194,15 +194,15 @@ 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'
})

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'
Expand Down