npm-check-updates
Version:
Find newer versions of dependencies than what your package.json allows
287 lines • 11.2 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.printIgnoredUpdates = exports.printUpgrades = exports.printUpgradesTable = exports.toDependencyTable = exports.printSorted = exports.printSimpleJoinedString = exports.printJson = exports.print = void 0;
/**
* Loggin functions.
*/
const cli_table3_1 = __importDefault(require("cli-table3"));
const transform_1 = __importDefault(require("lodash/transform"));
const chalk_1 = __importDefault(require("./chalk"));
const filterObject_1 = __importDefault(require("./filterObject"));
const getRepoUrl_1 = __importDefault(require("./getRepoUrl"));
const version_util_1 = require("./version-util");
// maps string levels to numeric levels
const logLevels = {
silent: 0,
error: 1,
minimal: 2,
warn: 3,
info: 4,
verbose: 5,
silly: 6,
};
/** Returns true if the dependency spec is not fetchable from the registry and is ignored. */
const isFetchable = (spec) => !spec.startsWith('file:') &&
!spec.startsWith('link:') &&
!spec.startsWith('workspace:') &&
// short github urls that are ignored, e.g. raineorshine/foo
!/^[^/:@]+\/\w+/.test(spec);
/**
* Prints a message if it is included within options.loglevel.
*
* @param options Command line options. These will be compared to the loglevel parameter to determine if the message gets printed.
* @param message The message to print
* @param loglevel silent|error|warn|info|verbose|silly
* @param method The console method to call. Default: 'log'.
*/
function print(options, message, loglevel = null, method = 'log') {
var _a;
// not in json mode
// not silent
// not at a loglevel under minimum specified
if (!options.json &&
options.loglevel !== 'silent' &&
(loglevel == null ||
logLevels[((_a = options.loglevel) !== null && _a !== void 0 ? _a : 'warn')] >= logLevels[loglevel])) {
console[method](message);
}
}
exports.print = print;
/** Pretty print a JSON object. */
function printJson(options, object) {
if (options.loglevel !== 'silent') {
console.log(JSON.stringify(object, null, 2));
}
}
exports.printJson = printJson;
/** Print JSON object keys as string joined by character. */
function printSimpleJoinedString(object, join) {
console.log(Object.keys(object)
.map(pkg => pkg + '@' + object[pkg])
.join(join));
}
exports.printSimpleJoinedString = printSimpleJoinedString;
/** Prints an object sorted by key. */
function printSorted(options, obj, loglevel) {
// eslint-disable-next-line fp/no-mutating-methods
const sortedKeys = Object.keys(obj).sort();
const objSorted = (0, transform_1.default)(sortedKeys, (accum, key) => {
accum[key] = obj[key];
}, {});
print(options, objSorted, loglevel);
}
exports.printSorted = printSorted;
/** Create a table with the appropriate columns and alignment to render dependency upgrades. */
function renderDependencyTable(rows) {
const table = new cli_table3_1.default({
colAligns: ['left', 'right', 'right', 'right', 'left', 'left'],
chars: {
top: '',
'top-mid': '',
'top-left': '',
'top-right': '',
bottom: '',
'bottom-mid': '',
'bottom-left': '',
'bottom-right': '',
left: '',
'left-mid': '',
mid: '',
'mid-mid': '',
right: '',
'right-mid': '',
middle: '',
},
});
// eslint-disable-next-line fp/no-mutating-methods
table.push(...rows);
// when border is removed, whitespace remains
// trim the end of each line to remove whitespace
// this makes no difference visually, but the whitespace interacts poorly with .editorconfig in tests
return table
.toString()
.split('\n')
.map(line => line.trimEnd())
.join('\n');
}
/**
* Extract just the version number from a package.json dep
*
* @param dep Raw dependency, could be version / npm: string / Git url
*/
function getVersion(dep) {
return (0, version_util_1.isGithubUrl)(dep) ? (0, version_util_1.getGithubUrlTag)(dep) : (0, version_util_1.isNpmAlias)(dep) ? (0, version_util_1.parseNpmAlias)(dep)[1] : dep;
}
/**
* Renders a color-coded table of upgrades.
*
* @param args
* @param args.from
* @param args.to
* @param args.ownersChangedDeps
* @param args.format
*/
async function toDependencyTable({ from: fromDeps, to: toDeps, format, ownersChangedDeps, pkgFile, time, }) {
const table = renderDependencyTable(await Promise.all(
// eslint-disable-next-line fp/no-mutating-methods
Object.keys(toDeps)
.sort()
.map(async (dep) => {
const from = fromDeps[dep] || '';
const toRaw = toDeps[dep] || '';
const to = getVersion(toRaw);
const ownerChanged = ownersChangedDeps
? dep in ownersChangedDeps
? ownersChangedDeps[dep]
? '*owner changed*'
: ''
: '*unknown*'
: '';
const toColorized = (0, version_util_1.colorizeDiff)(getVersion(from), to);
const repoUrl = (format === null || format === void 0 ? void 0 : format.includes('repo')) ? (await (0, getRepoUrl_1.default)(dep, undefined, { pkgFile })) || '' : '';
const publishTime = (format === null || format === void 0 ? void 0 : format.includes('time')) && (time === null || time === void 0 ? void 0 : time[dep]) ? time[dep] : '';
return [dep, from, '→', toColorized, ownerChanged, ...[repoUrl, publishTime].filter(x => x)];
})));
return table;
}
exports.toDependencyTable = toDependencyTable;
/**
* Renders one or more color-coded tables with all upgrades. Supports different formats from the --format option.
*
* @param args
* @param args.current
* @param args.upgraded
* @param args.ownersChangedDeps
* @param options
*/
async function printUpgradesTable({ current, upgraded, ownersChangedDeps, pkgFile, time, }, options) {
var _a, _b;
// group
if ((_a = options.format) === null || _a === void 0 ? void 0 : _a.includes('group')) {
const groups = (0, version_util_1.getDependencyGroups)(upgraded, current, options);
// eslint-disable-next-line fp/no-loops -- We must await in each iteration of the loop
for (const { heading, packages } of groups) {
print(options, '\n' + heading);
print(options, await toDependencyTable({
from: current,
to: packages,
format: options.format,
ownersChangedDeps,
pkgFile,
time,
}));
}
}
else {
if ((_b = options.format) === null || _b === void 0 ? void 0 : _b.includes('lines')) {
printSimpleJoinedString(upgraded, '\n');
}
else {
print(options, await toDependencyTable({
from: current,
to: upgraded,
format: options.format,
ownersChangedDeps,
pkgFile,
time,
}));
}
}
}
exports.printUpgradesTable = printUpgradesTable;
/** Prints errors. */
function printErrors(options, errors) {
if (!errors)
return;
if (Object.keys(errors).length > 0) {
const errorTable = new cli_table3_1.default({
colAligns: ['left', 'right', 'right', 'right', 'left', 'left'],
chars: {
top: '',
'top-mid': '',
'top-left': '',
'top-right': '',
bottom: '',
'bottom-mid': '',
'bottom-left': '',
'bottom-right': '',
left: '',
'left-mid': '',
mid: '',
'mid-mid': '',
right: '',
'right-mid': '',
middle: '',
},
});
// eslint-disable-next-line fp/no-mutating-methods
errorTable.push(...Object.entries(errors).map(([dep, error]) => [dep, chalk_1.default.yellow(error)]));
print(options, '\n' + errorTable.toString());
}
}
/**
* @param args.current -
* @param args.latest -
* @param args.upgraded -
* @param args.total -
* @param args.ownersChangedDeps -
*/
async function printUpgrades(options, { current, latest, upgraded, total, ownersChangedDeps, pkgFile, time, errors, }) {
var _a;
if (!((_a = options.format) === null || _a === void 0 ? void 0 : _a.includes('group'))) {
print(options, '');
}
const smiley = chalk_1.default.green.bold(':)');
const numErrors = Object.keys(errors || {}).length;
const target = typeof options.target === 'string' ? options.target : 'target';
const numUpgraded = Object.keys(upgraded).length;
if (numUpgraded === 0 && total === 0 && numErrors === 0) {
if (Object.keys(current).length === 0) {
print(options, 'No dependencies.');
}
else if (latest &&
Object.keys(latest).length === 0 &&
// some specs are ignored by ncu, like the file: protocol, so they should be ignored when detecting fetch issues
Object.values((0, filterObject_1.default)(current, (name, spec) => isFetchable(spec))).length > 0) {
print(options, `No package versions were returned. This may be a problem with your installed ${options.packageManager}, the npm registry, or your Internet connection. Make sure ${chalk_1.default.cyan('npx pacote packument ncu-test-v2')} is working before reporting an issue.`);
}
else if (options.global) {
print(options, `All global packages are up-to-date ${smiley}`);
}
else {
print(options, `All dependencies match the ${target} package versions ${smiley}`);
}
}
else if (numUpgraded === 0 && total > 0) {
print(options, `No dependencies upgraded ${smiley}`);
}
// print table
else if (numUpgraded > 0) {
await printUpgradesTable({
current,
upgraded,
ownersChangedDeps,
pkgFile,
time,
}, options);
}
printErrors(options, errors);
}
exports.printUpgrades = printUpgrades;
/** Print updates that were ignored due to incompatible peer dependencies. */
function printIgnoredUpdates(options, ignoredUpdates) {
print(options, `\nIgnored incompatible updates (peer dependencies):\n`);
const table = renderDependencyTable(Object.entries(ignoredUpdates).map(([pkgName, { from, to, reason }]) => {
const strReason = 'reason: ' +
Object.entries(reason)
.map(([pkgReason, requirement]) => pkgReason + ' requires ' + requirement)
.join(', ');
return [pkgName, from, '→', (0, version_util_1.colorizeDiff)(from, to), strReason];
}));
print(options, table);
}
exports.printIgnoredUpdates = printIgnoredUpdates;
//# sourceMappingURL=logging.js.map
;