danger-plugin-npm-check-updates
Version:
Danger plugin for npm-check-updates
182 lines (181 loc) • 9.36 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
const objectFilter = require("@arnaudnyc/object-filter");
const fs = require("fs");
const ncu = require("npm-check-updates");
const path = require("path");
const utils_1 = require("./utils");
const npmCheckUpdates = (options = {}, reporter = warn) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const { modified_files, created_files, deleted_files } = danger.git;
const changedFiles = [...modified_files, ...created_files, ...deleted_files];
const { monorepo = false, monorepoPrefix = 'packages', onlyChangedPackages = false, excludePackages, ignoreLockVersion = true } = options,
// tslint:disable-next-line: trailing-comma
runOptions = __rest(options, ["monorepo", "monorepoPrefix", "onlyChangedPackages", "excludePackages", "ignoreLockVersion"]);
const defaultBasePath = ((_a = runOptions.packageFile) === null || _a === void 0 ? void 0 : _a.replace('package.json', '')) || '.';
const defaultPackageJson = utils_1.readPackageJson(defaultBasePath);
const defaultPackageLock = !ignoreLockVersion
? utils_1.readPackageLock(defaultBasePath)
: null;
let packages = defaultPackageJson
? [
{
packageJson: defaultPackageJson,
packageLock: defaultPackageLock,
},
]
: [];
if (monorepo) {
const monorepoPackagesPattern = new RegExp(`${monorepoPrefix}\/(.+)\/`);
const monorepoPackagesChangedDir = changedFiles
.filter((file) => monorepoPackagesPattern.test(file))
.map((file) => {
const match = file.match(monorepoPackagesPattern);
if (Array.isArray(match)) {
return match[0].split('/')[1];
}
return [];
})
.filter((file, i, arr) => arr.indexOf(file) === i && !Array.isArray(file));
try {
const monorepoBasePath = path.join(defaultBasePath, monorepoPrefix);
const monorepoPackagesDir = onlyChangedPackages
? monorepoPackagesChangedDir
: fs.readdirSync(monorepoBasePath);
const monorepoPackages = monorepoPackagesDir
.filter((pkg) => {
try {
const basePath = path.join(monorepoBasePath, pkg.toString(), '/');
const packageJson = utils_1.readPackageJson(basePath);
return Boolean(packageJson);
}
catch (e) {
console.error(e.message);
return false;
}
})
.map((pkg) => {
const basePath = path.join(monorepoBasePath, pkg.toString(), '/');
return {
packageJson: utils_1.readPackageJson(basePath),
packageLock: !ignoreLockVersion ? utils_1.readPackageLock(basePath) : null,
};
});
packages = packages.concat(monorepoPackages);
// tslint:disable-next-line: no-empty
}
catch (e) {
console.error(e.message);
}
}
if (excludePackages) {
if (typeof excludePackages === 'string') {
packages = packages.filter((pkg) => { var _a; return excludePackages !== ((_a = pkg === null || pkg === void 0 ? void 0 : pkg.packageJson) === null || _a === void 0 ? void 0 : _a.name); });
}
else if (Array.isArray(excludePackages)) {
packages = packages.filter((pkg) => { var _a; return !excludePackages.includes((_a = pkg === null || pkg === void 0 ? void 0 : pkg.packageJson) === null || _a === void 0 ? void 0 : _a.name); });
}
else if (excludePackages instanceof RegExp) {
packages = packages.filter((pkg) => { var _a; return !excludePackages.test((_a = pkg === null || pkg === void 0 ? void 0 : pkg.packageJson) === null || _a === void 0 ? void 0 : _a.name); });
}
}
for (const { packageJson, packageLock } of packages) {
try {
const _options = Object.assign(Object.assign({}, runOptions), { packageData: JSON.stringify(packageJson) });
const getPackageLockVersion = (dep) => {
var _a, _b;
let result = '-';
if (packageLock) {
switch (packageLock.type) {
case 'npm':
result = (_a = packageLock.dependencies[dep]) === null || _a === void 0 ? void 0 : _a.version;
break;
case 'yarn':
const depNames = Object.keys(packageLock.object);
const depName = depNames.find((name) => new RegExp(`^${dep}@`).test(name));
if (depName) {
result = (_b = packageLock.object[depName]) === null || _b === void 0 ? void 0 : _b.version;
}
break;
}
}
return result;
};
const getPackageType = (dep) => {
let result = '-';
if (packageJson) {
const dependencyTypes = [
'dependencies',
'devDependencies',
'peerDependencies',
'optionalDependencies',
];
for (const type of dependencyTypes) {
const found = packageJson[type] &&
packageJson[type].constructor.name === 'Object'
? Object.keys(packageJson[type]).find((key) => key === dep)
: null;
if (found) {
result = type;
return result;
}
}
}
return result;
};
let ncuResult = yield ncu.run(_options);
if (!ignoreLockVersion) {
const filteredNcuResult = objectFilter(ncuResult, (key, value) => {
return !value.includes(getPackageLockVersion(key));
});
ncuResult = filteredNcuResult;
}
const outdatedDependenciesNames = Object.keys(ncuResult);
const currentDependencies = ncu.getCurrentDependencies(packageJson);
const outdatedDependencies = {};
for (const dep of outdatedDependenciesNames) {
outdatedDependencies[dep] = {
from: currentDependencies[dep] || '-',
to: ncuResult[dep] || '-',
lock: !ignoreLockVersion ? getPackageLockVersion(dep) : null,
packageType: getPackageType(dep),
url: `https://www.npmjs.com/package/${dep}`,
};
}
if (outdatedDependenciesNames.length) {
const table = outdatedDependenciesNames
.map((dependencyName) => {
const { from, to, lock, packageType, url } = outdatedDependencies[dependencyName];
return `<tr><td><a href="${url}" target="_blank">${dependencyName}</a></td>${!ignoreLockVersion ? `<td>${lock}</td>` : ''}<td>${from}</td><td>${to}</td><td>${packageType}</td></tr>`;
})
.join(' ');
reporter(`You have ${outdatedDependenciesNames.length} outdated dependencies in ${packageJson === null || packageJson === void 0 ? void 0 : packageJson.name}.\n
<details><summary>Show Lists</summary><table><thead><tr><th width="100%">Package</th>${!ignoreLockVersion ? `<th>Package Lock</th>` : ''}<th>From</th><th>To</th><th>Package Type</th></tr></thead>${table}</table></details>`);
}
}
catch (err) {
fail(`npm check updates error in ${packageJson === null || packageJson === void 0 ? void 0 : packageJson.name}: ` + err.message);
}
}
});
exports.default = npmCheckUpdates;