Skip to content

Commit

Permalink
Add installedVersion format option (#1449)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubdrozdek committed Aug 21, 2024
1 parent eae4692 commit a6f96a4
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 27 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ Options that take no arguments can be negated by prefixing them with `--no-`, e.
</tr>
<tr>
<td><a href="#format">--format &lt;value&gt;</a></td>
<td>Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines. (default: [])</td>
<td>Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines, installedVersion. (default: [])</td>
</tr>
<tr>
<td>-g, --global</td>
Expand Down Expand Up @@ -544,6 +544,7 @@ Modify the output formatting or show additional information. Specify one or more
<tr><td>repo</td><td>Infers and displays links to the package's source code repository. Requires packages to be installed.</td></tr>
<tr><td>time</td><td>Shows the publish time of each upgrade.</td></tr>
<tr><td>lines</td><td>Prints name@version on separate lines. Useful for piping to npm install.</td></tr>
<tr><td>installedVersion</td><td>Prints the exact current version number instead of a range.</td></tr>
</table>
## groupFunction
Expand Down
5 changes: 3 additions & 2 deletions src/cli-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ const extendedHelpFormat: ExtendedHelp = ({ markdown }) => {
['repo', `Infers and displays links to the package's source code repository. Requires packages to be installed.`],
['time', 'Shows the publish time of each upgrade.'],
['lines', 'Prints name@version on separate lines. Useful for piping to npm install.'],
['installedVersion', 'Prints the exact current version number instead of a range.'],
],
})

Expand Down Expand Up @@ -664,11 +665,11 @@ const cliOptions: CLIOption[] = [
long: 'format',
arg: 'value',
description:
'Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines.',
'Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines, installedVersion.',
parse: value => (typeof value === 'string' ? value.split(',') : value),
default: [],
type: 'string[]',
choices: ['group', 'ownerChanged', 'repo', 'time', 'lines'],
choices: ['group', 'ownerChanged', 'repo', 'time', 'lines', 'installedVersion'],
help: extendedHelpFormat,
},
{
Expand Down
34 changes: 34 additions & 0 deletions src/lib/getPackageJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fs from 'fs/promises'
import path from 'path'
import { PackageFile } from '../types/PackageFile'
import exists from './exists'

/** Gets the package.json contents of an installed package. */
async function getPackageJson(
packageName: string,
{
pkgFile,
}: {
/** Specify the package file location to add to the node_modules search paths. Needed in workspaces/deep mode. */
pkgFile?: string
} = {},
): Promise<PackageFile | null> {
const requirePaths = require.resolve.paths(packageName) || []
const pkgFileNodeModules = pkgFile ? [path.join(path.dirname(pkgFile), 'node_modules')] : []
const localNodeModules = [path.join(process.cwd(), 'node_modules')]
const nodeModulePaths = [...pkgFileNodeModules, ...localNodeModules, ...requirePaths]

for (const basePath of nodeModulePaths) {
const packageJsonPath = path.join(basePath, packageName, 'package.json')
if (await exists(packageJsonPath)) {
try {
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'))
return packageJson
} catch (e) {}
}
}

return null
}

export default getPackageJson
27 changes: 27 additions & 0 deletions src/lib/getPackageVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PackageFile } from '../types/PackageFile'
import getPackageJson from './getPackageJson'

/**
* @param packageName A package name as listed in package.json's dependencies list
* @param packageJson Optional param to specify a object representation of a package.json file instead of loading from node_modules
* @returns The package version or null if a version could not be determined
*/
async function getPackageVersion(
packageName: string,
packageJson?: PackageFile,
{
pkgFile,
}: {
/** Specify the package file location to add to the node_modules search paths. Needed in workspaces/deep mode. */
pkgFile?: string
} = {},
) {
if (packageJson) {
return packageJson.version
}

const loadedPackageJson = await getPackageJson(packageName, { pkgFile })
return loadedPackageJson?.version ?? null
}

export default getPackageVersion
24 changes: 4 additions & 20 deletions src/lib/getRepoUrl.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import fs from 'fs/promises'
import hostedGitInfo from 'hosted-git-info'
import path from 'path'
import { URL } from 'url'
import { PackageFile } from '../types/PackageFile'
import { PackageFileRepository } from '../types/PackageFileRepository'
import exists from './exists'
import getPackageJson from './getPackageJson'

/** Gets the repo url of an installed package. */
async function getPackageRepo(
Expand All @@ -15,23 +13,9 @@ async function getPackageRepo(
/** Specify the package file location to add to the node_modules search paths. Needed in workspaces/deep mode. */
pkgFile?: string
} = {},
): Promise<string | { url: string } | null> {
const requirePaths = require.resolve.paths(packageName) || []
const pkgFileNodeModules = pkgFile ? [path.join(path.dirname(pkgFile), 'node_modules')] : []
const localNodeModules = [path.join(process.cwd(), 'node_modules')]
const nodeModulePaths = [...pkgFileNodeModules, ...localNodeModules, ...requirePaths]

for (const basePath of nodeModulePaths) {
const packageJsonPath = path.join(basePath, packageName, 'package.json')
if (await exists(packageJsonPath)) {
try {
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'))
return packageJson.repository
} catch (e) {}
}
}

return null
): Promise<string | PackageFileRepository | null> {
const packageJson = await getPackageJson(packageName, { pkgFile })
return packageJson?.repository ?? null
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/lib/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { VersionResult } from '../types/VersionResult'
import { VersionSpec } from '../types/VersionSpec'
import chalk from './chalk'
import filterObject from './filterObject'
import getPackageVersion from './getPackageVersion'
import getRepoUrl from './getRepoUrl'
import {
colorizeDiff,
Expand Down Expand Up @@ -168,7 +169,10 @@ export async function toDependencyTable({
Object.keys(toDeps)
.sort()
.map(async dep => {
const from = fromDeps[dep] || ''
const from =
(format?.includes('installedVersion')
? await getPackageVersion(dep, undefined, { pkgFile })
: fromDeps[dep]) || ''
const toRaw = toDeps[dep] || ''
const to = getVersion(toRaw)
const ownerChanged = ownersChangedDeps
Expand Down
1 change: 1 addition & 0 deletions src/types/PackageFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export interface PackageFile {
repository?: string | PackageFileRepository
scripts?: Index<string>
workspaces?: string[] | { packages: string[] }
version?: string
}
5 changes: 4 additions & 1 deletion src/types/RunOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
"$ref": "#/definitions/Index<string>",
"description": "A very generic object."
},
"version": {
"type": "string"
},
"workspaces": {
"anyOf": [
{
Expand Down Expand Up @@ -284,7 +287,7 @@
"description": "Filter on package version using comma-or-space-delimited list, /regex/, or predicate function. Run \"ncu --help --filterVersion\" for details."
},
"format": {
"description": "Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines. Run \"ncu --help --format\" for details.",
"description": "Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines, installedVersion. Run \"ncu --help --format\" for details.",
"items": {
"type": "string"
},
Expand Down
2 changes: 1 addition & 1 deletion src/types/RunOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export interface RunOptions {
/** Filter on package version using comma-or-space-delimited list, /regex/, or predicate function. Run "ncu --help --filterVersion" for details. */
filterVersion?: string | RegExp | (string | RegExp)[] | FilterFunction

/** Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines. Run "ncu --help --format" for details. */
/** Modify the output formatting or show additional information. Specify one or more comma-delimited values: group, ownerChanged, repo, time, lines, installedVersion. Run "ncu --help --format" for details. */
format?: string[]

/** Check global packages instead of in the current project. */
Expand Down
2 changes: 1 addition & 1 deletion test/getIgnoredUpgradesDueToEnginesNode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe('getIgnoredUpgradesDueToEnginesNode', function () {
'@typescript-eslint/eslint-plugin': {
enginesNode: '^18.18.0 || ^20.9.0 || >=21.1.0',
from: '^7.18.0',
to: '^8.0.1',
to: '^8.2.0',
},
del: {
enginesNode: '>=14.16',
Expand Down

0 comments on commit a6f96a4

Please sign in to comment.