js-green-licenses
Advanced tools
Comparing version 0.5.0 to 1.0.0
@@ -21,5 +21,9 @@ /// <reference types="node" /> | ||
} | ||
export interface DefaultHandlerOptions { | ||
setExitCode?: boolean; | ||
} | ||
export declare class LicenseChecker extends EventEmitter { | ||
private readonly processedPackages; | ||
private readonly failedPackages; | ||
private readonly localPackages; | ||
private readonly opts; | ||
@@ -29,3 +33,3 @@ private config; | ||
private whitelistedLicenses; | ||
constructor({dev, verbose}?: LicenseCheckerOptions); | ||
constructor({ dev, verbose }?: LicenseCheckerOptions); | ||
on(event: 'non-green-license', listener: (arg: NonGreenLicense) => void): this; | ||
@@ -39,12 +43,12 @@ on(event: 'package.json', listener: (filePath: string) => void): this; | ||
emit(event: 'error', checkError: CheckError): boolean; | ||
private init(cfg); | ||
private getLicense(pkgJson); | ||
private correctLicenseName(license); | ||
private isPackageWhitelisted(packageName); | ||
private isGreenLicense(license); | ||
private checkLicenses(packageName, versionSpec, ...parents); | ||
private checkLicensesForDeps(deps, ...parents); | ||
private checkPackageJson(json, packageName, ...parents); | ||
private checkPackageJsonContent(content); | ||
private getLocalPackageJsonFiles(directory); | ||
private init; | ||
private getLicense; | ||
private correctLicenseName; | ||
private isPackageWhitelisted; | ||
private isGreenLicense; | ||
private checkLicenses; | ||
private checkLicensesForDeps; | ||
private checkPackageJson; | ||
private checkPackageJsonContent; | ||
private getLocalPackageJsonFiles; | ||
checkLocalDirectory(directory: string): Promise<void>; | ||
@@ -59,3 +63,3 @@ checkRemotePackage(pkg: string): Promise<void>; | ||
/** set default event handlers for CLI output. */ | ||
setDefaultHandlers(): void; | ||
setDefaultHandlers(options?: DefaultHandlerOptions): void; | ||
} |
@@ -15,47 +15,2 @@ "use strict"; | ||
// limitations under the License. | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
@@ -67,75 +22,102 @@ if (mod && mod.__esModule) return mod; | ||
return result; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var events_1 = require("events"); | ||
var fs = __importStar(require("fs")); | ||
var npm_package_arg_1 = __importDefault(require("npm-package-arg")); | ||
var package_json_1 = __importDefault(require("package-json")); | ||
var path = __importStar(require("path")); | ||
var pify_1 = __importDefault(require("pify")); | ||
var spdx_correct_1 = __importDefault(require("spdx-correct")); | ||
var spdx_satisfies_1 = __importDefault(require("spdx-satisfies")); | ||
var util_1 = require("util"); | ||
var config = __importStar(require("./config")); | ||
var github_1 = require("./github"); | ||
var package_json_file_1 = require("./package-json-file"); | ||
const events_1 = require("events"); | ||
const fs = __importStar(require("fs")); | ||
const npm_package_arg_1 = __importDefault(require("npm-package-arg")); | ||
const package_json_1 = __importDefault(require("package-json")); | ||
const path = __importStar(require("path")); | ||
const spdx_correct_1 = __importDefault(require("spdx-correct")); | ||
const spdx_satisfies_1 = __importDefault(require("spdx-satisfies")); | ||
const util_1 = require("util"); | ||
const config = __importStar(require("./config")); | ||
const github_1 = require("./github"); | ||
const package_json_file_1 = require("./package-json-file"); | ||
var github_2 = require("./github"); | ||
exports.GitHubRepository = github_2.GitHubRepository; | ||
var fsAccess = pify_1.default(fs.access); | ||
var fsReadDir = pify_1.default(fs.readdir); | ||
var fsReadFile = pify_1.default(fs.readFile); | ||
const fsAccess = util_1.promisify(fs.access); | ||
const fsReadDir = util_1.promisify(fs.readdir); | ||
const fsReadFile = util_1.promisify(fs.readFile); | ||
// Valid license IDs defined in https://spdx.org/licenses/ must be used whenever | ||
// possible. When adding new licenses, please consult the relevant documents. | ||
var DEFAULT_GREEN_LICENSES = [ | ||
'AFL-2.1', 'AFL-3.0', 'APSL-2.0', 'Apache-1.1', 'Apache-2.0', | ||
'Artistic-1.0', 'Artistic-2.0', 'BSD-2-Clause', 'BSD-3-Clause', 'BSL-1.0', | ||
'CC-BY-1.0', 'CC-BY-2.0', 'CC-BY-2.5', 'CC-BY-3.0', 'CC-BY-4.0', | ||
'CC0-1.0', 'CDDL-1.0', 'CDDL-1.1', 'CPL-1.0', 'EPL-1.0', | ||
'FTL', 'IPL-1.0', 'ISC', 'LGPL-2.0', 'LGPL-2.1', | ||
'LGPL-3.0', 'LPL-1.02', 'MIT', 'MPL-1.0', 'MPL-1.1', | ||
'MPL-2.0', 'MS-PL', 'NCSA', 'OpenSSL', 'PHP-3.0', | ||
'Ruby', 'Unlicense', 'W3C', 'Xnet', 'ZPL-2.0', | ||
'Zend-2.0', 'Zlib', 'libtiff', | ||
const DEFAULT_GREEN_LICENSES = [ | ||
'AFL-2.1', | ||
'AFL-3.0', | ||
'APSL-2.0', | ||
'Apache-1.1', | ||
'Apache-2.0', | ||
'Artistic-1.0', | ||
'Artistic-2.0', | ||
'BSD-2-Clause', | ||
'BSD-3-Clause', | ||
'BSL-1.0', | ||
'CC-BY-1.0', | ||
'CC-BY-2.0', | ||
'CC-BY-2.5', | ||
'CC-BY-3.0', | ||
'CC-BY-4.0', | ||
'CC0-1.0', | ||
'CDDL-1.0', | ||
'CDDL-1.1', | ||
'CPL-1.0', | ||
'EPL-1.0', | ||
'FTL', | ||
'IPL-1.0', | ||
'ISC', | ||
'LGPL-2.0', | ||
'LGPL-2.1', | ||
'LGPL-3.0', | ||
'LPL-1.02', | ||
'MIT', | ||
'MPL-1.0', | ||
'MPL-1.1', | ||
'MPL-2.0', | ||
'MS-PL', | ||
'NCSA', | ||
'OpenSSL', | ||
'PHP-3.0', | ||
'Ruby', | ||
'Unlicense', | ||
'W3C', | ||
'Xnet', | ||
'ZPL-2.0', | ||
'Zend-2.0', | ||
'Zlib', | ||
'libtiff', | ||
]; | ||
var LicenseChecker = /** @class */ (function (_super) { | ||
__extends(LicenseChecker, _super); | ||
function LicenseChecker(_a) { | ||
var _b = _a === void 0 ? {} : _a, _c = _b.dev, dev = _c === void 0 ? false : _c, _d = _b.verbose, verbose = _d === void 0 ? false : _d; | ||
var _this = _super.call(this) || this; | ||
class LicenseChecker extends events_1.EventEmitter { | ||
constructor({ dev = false, verbose = false } = {}) { | ||
super(); | ||
// Cache for packageName@version's that are already processed. | ||
_this.processedPackages = new Set(); | ||
this.processedPackages = new Set(); | ||
// Cache for packageName@version's that failed for fetching. | ||
_this.failedPackages = new Set(); | ||
_this.config = {}; | ||
this.failedPackages = new Set(); | ||
// Local packages, for monorepo | ||
this.localPackages = new Set(); | ||
this.config = {}; | ||
// Licenses in this expression must be valid license IDs defined in | ||
// https://spdx.org/licenses/. | ||
_this.greenLicenseExpr = ''; | ||
this.greenLicenseExpr = ''; | ||
// List of license names that are not SPDX-conforming IDs but are allowed. | ||
_this.whitelistedLicenses = []; | ||
_this.opts = { dev: dev, verbose: verbose }; | ||
return _this; | ||
this.whitelistedLicenses = []; | ||
this.opts = { dev, verbose }; | ||
} | ||
// tslint:disable-next-line:no-any `EventEmitter` uses ...args: any[] | ||
LicenseChecker.prototype.on = function (event, listener) { | ||
return _super.prototype.on.call(this, event, listener); | ||
}; | ||
on(event, listener) { | ||
return super.on(event, listener); | ||
} | ||
// tslint:disable-next-line:no-any `EventEmitter` uses ...args: any[] | ||
LicenseChecker.prototype.emit = function (event) { | ||
var args = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
args[_i - 1] = arguments[_i]; | ||
} | ||
return _super.prototype.emit.apply(this, [event].concat(args)); | ||
}; | ||
LicenseChecker.prototype.init = function (cfg) { | ||
emit(event, ...args) { | ||
return super.emit(event, ...args); | ||
} | ||
init(cfg) { | ||
this.config = cfg || {}; | ||
var greenLicenses = this.config.greenLicenses || DEFAULT_GREEN_LICENSES; | ||
var validGreenLicenses = []; | ||
var invalidGreenLicenses = []; | ||
for (var _i = 0, greenLicenses_1 = greenLicenses; _i < greenLicenses_1.length; _i++) { | ||
var license = greenLicenses_1[_i]; | ||
var corrected = this.correctLicenseName(license); | ||
const greenLicenses = this.config.greenLicenses || DEFAULT_GREEN_LICENSES; | ||
const validGreenLicenses = []; | ||
const invalidGreenLicenses = []; | ||
for (const license of greenLicenses) { | ||
const corrected = this.correctLicenseName(license); | ||
if (corrected) { | ||
@@ -148,8 +130,8 @@ validGreenLicenses.push(corrected); | ||
} | ||
this.greenLicenseExpr = "(" + validGreenLicenses.join(' OR ') + ")"; | ||
this.greenLicenseExpr = `(${validGreenLicenses.join(' OR ')})`; | ||
this.whitelistedLicenses = invalidGreenLicenses; | ||
this.processedPackages.clear(); | ||
this.failedPackages.clear(); | ||
}; | ||
LicenseChecker.prototype.getLicense = function (pkgJson) { | ||
} | ||
getLicense(pkgJson) { | ||
// Some package.json files have incorrect license fields, and old packages | ||
@@ -159,31 +141,35 @@ // may have legacy licence field format. See | ||
// below is a little complicated to deal with those cases. | ||
var license = pkgJson.license || pkgJson.licenses; | ||
if (!license) | ||
const license = pkgJson.license || pkgJson.licenses; | ||
if (!license) { | ||
if (pkgJson.private) { | ||
return 'private'; | ||
} | ||
return null; | ||
} | ||
if (typeof license === 'string') | ||
return license; | ||
if (Array.isArray(license)) { | ||
var types = license.map(function (x) { return x.type; }).filter(function (x) { return !!x; }); | ||
return types.length === 1 ? types[0] : "(" + types.join(' OR ') + ")"; | ||
const types = license.map(x => x.type).filter(x => !!x); | ||
return types.length === 1 ? types[0] : `(${types.join(' OR ')})`; | ||
} | ||
return license.type || null; | ||
}; | ||
LicenseChecker.prototype.correctLicenseName = function (license) { | ||
var corrected = spdx_correct_1.default(license); | ||
} | ||
correctLicenseName(license) { | ||
const corrected = spdx_correct_1.default(license); | ||
if (this.opts.verbose && corrected && corrected !== license) { | ||
console.warn("Correcting " + license + " to " + corrected); | ||
console.warn(`Correcting ${license} to ${corrected}`); | ||
} | ||
return corrected; | ||
}; | ||
LicenseChecker.prototype.isPackageWhitelisted = function (packageName) { | ||
return !!this.config.packageWhitelist && | ||
this.config.packageWhitelist.some(function (p) { return p === packageName; }); | ||
}; | ||
LicenseChecker.prototype.isGreenLicense = function (license) { | ||
} | ||
isPackageWhitelisted(packageName) { | ||
return (!!this.config.packageWhitelist && | ||
this.config.packageWhitelist.some(p => p === packageName)); | ||
} | ||
isGreenLicense(license) { | ||
if (!license) | ||
return false; | ||
var correctedName = this.correctLicenseName(license); | ||
const correctedName = this.correctLicenseName(license); | ||
// `license` is not a valid or correctable SPDX id. Check the whitelist. | ||
if (!correctedName) { | ||
return this.whitelistedLicenses.some(function (l) { return l === license; }); | ||
return this.whitelistedLicenses.some(l => l === license); | ||
} | ||
@@ -200,361 +186,209 @@ try { | ||
} | ||
}; | ||
LicenseChecker.prototype.checkLicenses = function (packageName, versionSpec) { | ||
var parents = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
parents[_i - 2] = arguments[_i]; | ||
} | ||
async checkLicenses(packageName, versionSpec, ...parents) { | ||
const spec = `${packageName}@${versionSpec}`; | ||
if (this.failedPackages.has(spec)) | ||
return; | ||
// remove tilde/caret to check for an exact version, ^0.5.0-rc.0 becomes 0.5.0-rc.0 | ||
const version = versionSpec.replace(/^[^~]/, ''); | ||
// if the dependency is a local package then skip verification at this step. will be checked independently | ||
if (this.localPackages.has(`${packageName}@${version}`)) | ||
return; | ||
try { | ||
const json = await package_json_1.default(packageName, { | ||
version: versionSpec, | ||
fullMetadata: true, | ||
}); | ||
await this.checkPackageJson(json, packageName, ...parents); | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var spec, json, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
spec = packageName + "@" + versionSpec; | ||
if (this.failedPackages.has(spec)) | ||
return [2 /*return*/]; | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 4, , 5]); | ||
return [4 /*yield*/, package_json_1.default(packageName, { version: versionSpec, fullMetadata: true })]; | ||
case 2: | ||
json = _a.sent(); | ||
return [4 /*yield*/, this.checkPackageJson.apply(this, [json, packageName].concat(parents))]; | ||
case 3: | ||
_a.sent(); | ||
return [3 /*break*/, 5]; | ||
case 4: | ||
err_1 = _a.sent(); | ||
this.failedPackages.add(spec); | ||
this.emit('error', { | ||
err: err_1, | ||
packageName: packageName, | ||
versionSpec: versionSpec, | ||
parentPackages: parents, | ||
}); | ||
return [3 /*break*/, 5]; | ||
case 5: return [2 /*return*/]; | ||
} | ||
catch (err) { | ||
this.failedPackages.add(spec); | ||
this.emit('error', { | ||
err, | ||
packageName, | ||
versionSpec, | ||
parentPackages: parents, | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.checkLicensesForDeps = function (deps) { | ||
var parents = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
parents[_i - 1] = arguments[_i]; | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, _b, pkg, depVersion; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (!deps) | ||
return [2 /*return*/]; | ||
_a = 0, _b = Object.keys(deps); | ||
_c.label = 1; | ||
case 1: | ||
if (!(_a < _b.length)) return [3 /*break*/, 4]; | ||
pkg = _b[_a]; | ||
depVersion = deps[pkg]; | ||
return [4 /*yield*/, this.checkLicenses.apply(this, [pkg, depVersion].concat(parents))]; | ||
case 2: | ||
_c.sent(); | ||
_c.label = 3; | ||
case 3: | ||
_a++; | ||
return [3 /*break*/, 1]; | ||
case 4: return [2 /*return*/]; | ||
} | ||
} | ||
async checkLicensesForDeps(deps, ...parents) { | ||
if (!deps) | ||
return; | ||
for (const pkg of Object.keys(deps)) { | ||
const depVersion = deps[pkg]; | ||
await this.checkLicenses(pkg, depVersion, ...parents); | ||
} | ||
} | ||
async checkPackageJson(json, packageName, ...parents) { | ||
const pj = package_json_file_1.ensurePackageJson(json); | ||
if (!packageName) { | ||
packageName = pj.name; | ||
} | ||
if (pj.name !== packageName) { | ||
console.warn(`Package name mismatch. Expected ${packageName}, but got ${pj.name}`); | ||
} | ||
const pkgVersion = pj.version; | ||
const packageAndVersion = `${packageName}@${pkgVersion}`; | ||
if (this.processedPackages.has(packageAndVersion)) | ||
return; | ||
this.processedPackages.add(packageAndVersion); | ||
if (this.isPackageWhitelisted(packageName)) { | ||
console.log(`${packageName} is whitelisted.`); | ||
} | ||
else { | ||
const license = this.getLicense(pj); | ||
if (!this.isGreenLicense(license)) { | ||
this.emit('non-green-license', { | ||
packageName, | ||
version: pkgVersion, | ||
licenseName: license, | ||
parentPackages: parents, | ||
}); | ||
} | ||
} | ||
await this.checkLicensesForDeps(pj.dependencies, ...parents, packageAndVersion); | ||
if (this.opts.dev) { | ||
await this.checkLicensesForDeps(pj.devDependencies, ...parents, packageAndVersion); | ||
} | ||
} | ||
async checkPackageJsonContent(content) { | ||
// tslint:disable-next-line:no-any `JSON.parse()` returns any | ||
let json = null; | ||
try { | ||
json = JSON.parse(content); | ||
await this.checkPackageJson(json, json.name); | ||
} | ||
catch (err) { | ||
const packageName = (json && json.name) || '(unknown package)'; | ||
const versionSpec = (json && json.version) || '(unknown version)'; | ||
this.emit('error', { | ||
err, | ||
packageName, | ||
versionSpec, | ||
parentPackages: [], | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.checkPackageJson = function (json, packageName) { | ||
var parents = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
parents[_i - 2] = arguments[_i]; | ||
} | ||
return __awaiter(this, void 0, void 0, function () { | ||
var pj, pkgVersion, packageAndVersion, license; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
pj = package_json_file_1.ensurePackageJson(json); | ||
if (!packageName) { | ||
packageName = pj.name; | ||
} | ||
if (pj.name !== packageName) { | ||
console.warn("Package name mismatch. Expected " + packageName + ", but got " + pj.name); | ||
} | ||
pkgVersion = pj.version; | ||
packageAndVersion = packageName + "@" + pkgVersion; | ||
if (this.processedPackages.has(packageAndVersion)) | ||
return [2 /*return*/]; | ||
this.processedPackages.add(packageAndVersion); | ||
if (this.isPackageWhitelisted(packageName)) { | ||
console.log(packageName + " is whitelisted."); | ||
} | ||
else { | ||
license = this.getLicense(pj); | ||
if (!this.isGreenLicense(license)) { | ||
this.emit('non-green-license', { | ||
packageName: packageName, | ||
version: pkgVersion, | ||
licenseName: license, | ||
parentPackages: parents, | ||
}); | ||
} | ||
} | ||
return [4 /*yield*/, this.checkLicensesForDeps.apply(this, [pj.dependencies].concat(parents, [packageAndVersion]))]; | ||
case 1: | ||
_a.sent(); | ||
if (!this.opts.dev) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, this.checkLicensesForDeps.apply(this, [pj.devDependencies].concat(parents, [packageAndVersion]))]; | ||
case 2: | ||
_a.sent(); | ||
_a.label = 3; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.checkPackageJsonContent = function (content) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var json, err_2, packageName, versionSpec; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
json = null; | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
json = JSON.parse(content); | ||
return [4 /*yield*/, this.checkPackageJson(json, json.name)]; | ||
case 2: | ||
_a.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
err_2 = _a.sent(); | ||
packageName = (json && json.name) || '(unknown package)'; | ||
versionSpec = (json && json.version) || '(unknown version)'; | ||
this.emit('error', { | ||
err: err_2, | ||
packageName: packageName, | ||
versionSpec: versionSpec, | ||
parentPackages: [], | ||
}); | ||
return [3 /*break*/, 4]; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.getLocalPackageJsonFiles = function (directory) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
var packageJsons, addPackageJson, packages, subpackages, _i, subpackages_1, dir, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
packageJsons = []; | ||
addPackageJson = function (dir) { return __awaiter(_this, void 0, void 0, function () { | ||
var pj, _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_b.trys.push([0, 2, , 3]); | ||
pj = path.join(dir, 'package.json'); | ||
return [4 /*yield*/, fsAccess(pj)]; | ||
case 1: | ||
_b.sent(); | ||
packageJsons.push(pj); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
_a = _b.sent(); | ||
return [3 /*break*/, 3]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); }; | ||
// Find the top-level package.json first. | ||
return [4 /*yield*/, addPackageJson(directory)]; | ||
case 1: | ||
// Find the top-level package.json first. | ||
_b.sent(); | ||
_b.label = 2; | ||
case 2: | ||
_b.trys.push([2, 8, , 9]); | ||
packages = path.join(directory, 'packages'); | ||
return [4 /*yield*/, fsReadDir(packages)]; | ||
case 3: | ||
subpackages = _b.sent(); | ||
_i = 0, subpackages_1 = subpackages; | ||
_b.label = 4; | ||
case 4: | ||
if (!(_i < subpackages_1.length)) return [3 /*break*/, 7]; | ||
dir = subpackages_1[_i]; | ||
return [4 /*yield*/, addPackageJson(path.join(packages, dir))]; | ||
case 5: | ||
_b.sent(); | ||
_b.label = 6; | ||
case 6: | ||
_i++; | ||
return [3 /*break*/, 4]; | ||
case 7: return [3 /*break*/, 9]; | ||
case 8: | ||
_a = _b.sent(); | ||
return [3 /*break*/, 9]; | ||
case 9: return [2 /*return*/, packageJsons]; | ||
} | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.checkLocalDirectory = function (directory) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, packageJsons, _i, packageJsons_1, pj, content; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a = this.init; | ||
return [4 /*yield*/, config.getLocalConfig(directory)]; | ||
case 1: | ||
_a.apply(this, [_b.sent()]); | ||
return [4 /*yield*/, this.getLocalPackageJsonFiles(directory)]; | ||
case 2: | ||
packageJsons = _b.sent(); | ||
if (packageJsons.length === 0) { | ||
console.log('No package.json files have been found.'); | ||
} | ||
_i = 0, packageJsons_1 = packageJsons; | ||
_b.label = 3; | ||
case 3: | ||
if (!(_i < packageJsons_1.length)) return [3 /*break*/, 7]; | ||
pj = packageJsons_1[_i]; | ||
this.emit('package.json', pj); | ||
return [4 /*yield*/, fsReadFile(pj, 'utf8')]; | ||
case 4: | ||
content = _b.sent(); | ||
return [4 /*yield*/, this.checkPackageJsonContent(content)]; | ||
case 5: | ||
_b.sent(); | ||
_b.label = 6; | ||
case 6: | ||
_i++; | ||
return [3 /*break*/, 3]; | ||
case 7: | ||
this.emit('end'); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
LicenseChecker.prototype.checkRemotePackage = function (pkg) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, pkgArgs, pkgType; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
// For checking remote packages, use config file in the current directory. | ||
_a = this.init; | ||
return [4 /*yield*/, config.getLocalConfig(process.cwd())]; | ||
case 1: | ||
// For checking remote packages, use config file in the current directory. | ||
_a.apply(this, [_b.sent()]); | ||
pkgArgs = npm_package_arg_1.default(pkg); | ||
pkgType = pkgArgs.type; | ||
if (!['tag', 'version', 'range'].some(function (type) { return type === pkgType; })) { | ||
throw new Error("Unsupported package spec: " + pkg); | ||
} | ||
if (!pkgArgs.name || !pkgArgs.fetchSpec) { | ||
throw new Error("Invalid package spec: " + pkg); | ||
} | ||
return [4 /*yield*/, this.checkLicenses(pkgArgs.name, pkgArgs.fetchSpec)]; | ||
case 2: | ||
_b.sent(); | ||
this.emit('end'); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
} | ||
async getLocalPackageJsonFiles(directory) { | ||
const packageJsons = []; | ||
const addPackageJson = async (dir) => { | ||
try { | ||
const pj = path.join(dir, 'package.json'); | ||
await fsAccess(pj); | ||
packageJsons.push(pj); | ||
} | ||
catch (_a) { | ||
// package.json doesn't exist. Ignore. | ||
} | ||
}; | ||
// Find the top-level package.json first. | ||
await addPackageJson(directory); | ||
// Find `packages/<name>/package.json` files in case this is a monorepo. | ||
try { | ||
const packages = path.join(directory, 'packages'); | ||
const subpackages = await fsReadDir(packages); | ||
// This is a monorepo. Find package.json from each directory under | ||
// `packages`. | ||
for (const dir of subpackages) { | ||
await addPackageJson(path.join(packages, dir)); | ||
} | ||
} | ||
catch (_a) { | ||
// The `packages` directory doesn't exist. Not a monorepo. Return just the | ||
// top-level package.json. | ||
} | ||
return packageJsons; | ||
} | ||
async checkLocalDirectory(directory) { | ||
this.init(await config.getLocalConfig(directory)); | ||
const packageJsons = await this.getLocalPackageJsonFiles(directory); | ||
if (packageJsons.length === 0) { | ||
console.log('No package.json files have been found.'); | ||
} | ||
for (const pj of packageJsons) { | ||
const content = await fsReadFile(pj, 'utf8'); | ||
const json = JSON.parse(content); | ||
if (json && json.name && json.version) { | ||
this.localPackages.add(`${json.name}@${json.version}`); | ||
} | ||
} | ||
for (const pj of packageJsons) { | ||
this.emit('package.json', pj); | ||
const content = await fsReadFile(pj, 'utf8'); | ||
await this.checkPackageJsonContent(content); | ||
} | ||
this.emit('end'); | ||
} | ||
async checkRemotePackage(pkg) { | ||
// For checking remote packages, use config file in the current directory. | ||
this.init(await config.getLocalConfig(process.cwd())); | ||
const pkgArgs = npm_package_arg_1.default(pkg); | ||
const pkgType = pkgArgs.type; | ||
if (!['tag', 'version', 'range'].some(type => type === pkgType)) { | ||
throw new Error(`Unsupported package spec: ${pkg}`); | ||
} | ||
if (!pkgArgs.name || !pkgArgs.fetchSpec) { | ||
throw new Error(`Invalid package spec: ${pkg}`); | ||
} | ||
await this.checkLicenses(pkgArgs.name, pkgArgs.fetchSpec); | ||
this.emit('end'); | ||
} | ||
/** @param prPath Must be in a form of <owner>/<repo>/pull/<id>. */ | ||
LicenseChecker.prototype.prPathToGitHubRepoAndId = function (prPath) { | ||
var regexp = /^([^/]+)\/([^/]+)\/pull\/(\d+)$/; | ||
var matched = regexp.exec(prPath); | ||
prPathToGitHubRepoAndId(prPath) { | ||
const regexp = /^([^/]+)\/([^/]+)\/pull\/(\d+)$/; | ||
const matched = regexp.exec(prPath); | ||
if (!matched) { | ||
throw new Error("Invalid github pull request path: " + prPath + ". " + | ||
throw new Error(`Invalid github pull request path: ${prPath}. ` + | ||
'Must be in the form <owner>/<repo>/pull/<id>.'); | ||
} | ||
var owner = matched[1], repoName = matched[2], prId = matched[3]; | ||
const [, owner, repoName, prId] = matched; | ||
return { repo: new github_1.GitHubRepository(owner, repoName), prId: Number(prId) }; | ||
}; | ||
LicenseChecker.prototype.checkGitHubPR = function (repo, mergeCommitSha) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, packageJsons, _i, packageJsons_2, pj; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a = this.init; | ||
return [4 /*yield*/, config.getGitHubConfig(repo, mergeCommitSha)]; | ||
case 1: | ||
_a.apply(this, [_b.sent()]); | ||
return [4 /*yield*/, repo.getPackageJsonFiles(mergeCommitSha)]; | ||
case 2: | ||
packageJsons = _b.sent(); | ||
if (packageJsons.length === 0) { | ||
console.log('No package.json files have been found.'); | ||
} | ||
_i = 0, packageJsons_2 = packageJsons; | ||
_b.label = 3; | ||
case 3: | ||
if (!(_i < packageJsons_2.length)) return [3 /*break*/, 6]; | ||
pj = packageJsons_2[_i]; | ||
this.emit('package.json', pj.filePath); | ||
return [4 /*yield*/, this.checkPackageJsonContent(pj.content)]; | ||
case 4: | ||
_b.sent(); | ||
_b.label = 5; | ||
case 5: | ||
_i++; | ||
return [3 /*break*/, 3]; | ||
case 6: | ||
this.emit('end'); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
} | ||
async checkGitHubPR(repo, mergeCommitSha) { | ||
this.init(await config.getGitHubConfig(repo, mergeCommitSha)); | ||
const packageJsons = await repo.getPackageJsonFiles(mergeCommitSha); | ||
if (packageJsons.length === 0) { | ||
console.log('No package.json files have been found.'); | ||
} | ||
for (const pj of packageJsons) { | ||
this.emit('package.json', pj.filePath); | ||
await this.checkPackageJsonContent(pj.content); | ||
} | ||
this.emit('end'); | ||
} | ||
/** set default event handlers for CLI output. */ | ||
LicenseChecker.prototype.setDefaultHandlers = function () { | ||
var nonGreenCount = 0; | ||
var errorCount = 0; | ||
this.on('non-green-license', function (_a) { | ||
var packageName = _a.packageName, version = _a.version, licenseName = _a.licenseName, parentPackages = _a.parentPackages; | ||
setDefaultHandlers(options = {}) { | ||
let nonGreenCount = 0; | ||
let errorCount = 0; | ||
this.on('non-green-license', ({ packageName, version, licenseName, parentPackages }) => { | ||
nonGreenCount++; | ||
var licenseDisplay = licenseName || '(no license)'; | ||
var packageAndVersion = packageName + "@" + version; | ||
console.log(licenseDisplay + ": " + packageAndVersion); | ||
console.log(" " + parentPackages.concat([packageAndVersion]).join(' -> ')); | ||
const licenseDisplay = licenseName || '(no license)'; | ||
const packageAndVersion = `${packageName}@${version}`; | ||
console.log(`${licenseDisplay}: ${packageAndVersion}`); | ||
console.log(` ${[...parentPackages, packageAndVersion].join(' -> ')}`); | ||
console.log(); | ||
}) | ||
.on('package.json', function (filePath) { | ||
console.log("Checking " + filePath + "..."); | ||
.on('package.json', filePath => { | ||
console.log(`Checking ${filePath}...`); | ||
console.log(); | ||
}) | ||
.on('error', function (_a) { | ||
var err = _a.err, packageName = _a.packageName, versionSpec = _a.versionSpec, parentPackages = _a.parentPackages; | ||
.on('error', ({ err, packageName, versionSpec, parentPackages }) => { | ||
errorCount++; | ||
var packageAndVersion = packageName + "@" + versionSpec; | ||
console.log("Error while checking " + packageAndVersion + ":"); | ||
console.log(" " + parentPackages.concat([packageAndVersion]).join(' -> ')); | ||
const packageAndVersion = `${packageName}@${versionSpec}`; | ||
console.log(`Error while checking ${packageAndVersion}:`); | ||
console.log(` ${[...parentPackages, packageAndVersion].join(' -> ')}`); | ||
console.log(); | ||
console.log("" + util_1.inspect(err)); | ||
console.log(`${util_1.inspect(err)}`); | ||
console.log(); | ||
}) | ||
.on('end', function () { | ||
.on('end', () => { | ||
if (nonGreenCount > 0 || errorCount > 0) { | ||
process.exitCode = 1; | ||
if (options.setExitCode) { | ||
process.exitCode = 1; | ||
} | ||
if (nonGreenCount > 0) { | ||
console.log(nonGreenCount + " non-green licenses found."); | ||
console.log(`${nonGreenCount} non-green licenses found.`); | ||
} | ||
if (errorCount > 0) { | ||
console.log(errorCount + " errors found."); | ||
console.log(`${errorCount} errors found.`); | ||
} | ||
@@ -566,6 +400,5 @@ } | ||
}); | ||
}; | ||
return LicenseChecker; | ||
}(events_1.EventEmitter)); | ||
} | ||
} | ||
exports.LicenseChecker = LicenseChecker; | ||
//# sourceMappingURL=checker.js.map |
@@ -0,1 +1,2 @@ | ||
#!/usr/bin/env node | ||
export {}; |
#!/usr/bin/env node | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
// Copyright 2017 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var argparse_1 = require("argparse"); | ||
var checker_1 = require("./checker"); | ||
var version = require('../../package.json').version; | ||
var argParser = new argparse_1.ArgumentParser({ | ||
version: version, | ||
const argparse_1 = require("argparse"); | ||
const checker_1 = require("./checker"); | ||
const version = require('../../package.json').version; | ||
const argParser = new argparse_1.ArgumentParser({ | ||
version, | ||
addHelp: true, | ||
@@ -74,41 +52,27 @@ description: 'License checker for npm modules', | ||
}); | ||
var args = argParser.parseArgs(); | ||
function main() { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var checker, _a, repo, prId, mergeCommitSha; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
checker = new checker_1.LicenseChecker({ dev: !!args.dev, verbose: !!args.verbose }); | ||
checker.setDefaultHandlers(); | ||
if (!args.local) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, checker.checkLocalDirectory(args.local[0])]; | ||
case 1: | ||
_b.sent(); | ||
return [3 /*break*/, 8]; | ||
case 2: | ||
if (!args.pr) return [3 /*break*/, 5]; | ||
_a = checker.prPathToGitHubRepoAndId(args.pr[0]), repo = _a.repo, prId = _a.prId; | ||
return [4 /*yield*/, repo.getPRCommits(prId)]; | ||
case 3: | ||
mergeCommitSha = (_b.sent()).mergeCommitSha; | ||
return [4 /*yield*/, checker.checkGitHubPR(repo, mergeCommitSha)]; | ||
case 4: | ||
_b.sent(); | ||
return [3 /*break*/, 8]; | ||
case 5: | ||
if (!args.package) return [3 /*break*/, 7]; | ||
return [4 /*yield*/, checker.checkRemotePackage(args.package)]; | ||
case 6: | ||
_b.sent(); | ||
return [3 /*break*/, 8]; | ||
case 7: throw new Error('Package name, --local, or --pr must be given'); | ||
case 8: return [2 /*return*/]; | ||
} | ||
}); | ||
const args = argParser.parseArgs(); | ||
async function main() { | ||
const checker = new checker_1.LicenseChecker({ | ||
dev: !!args.dev, | ||
verbose: !!args.verbose, | ||
}); | ||
checker.setDefaultHandlers({ setExitCode: true }); | ||
if (args.local) { | ||
await checker.checkLocalDirectory(args.local[0]); | ||
} | ||
else if (args.pr) { | ||
const { repo, prId } = checker.prPathToGitHubRepoAndId(args.pr[0]); | ||
const { mergeCommitSha } = await repo.getPRCommits(prId); | ||
await checker.checkGitHubPR(repo, mergeCommitSha); | ||
} | ||
else if (args.package) { | ||
await checker.checkRemotePackage(args.package); | ||
} | ||
else { | ||
throw new Error('Package name, --local, or --pr must be given'); | ||
} | ||
} | ||
main().catch(function (err) { | ||
main().catch(err => { | ||
console.error(err); | ||
}); | ||
//# sourceMappingURL=cli.js.map |
@@ -15,37 +15,2 @@ "use strict"; | ||
// limitations under the License. | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
@@ -57,21 +22,20 @@ if (mod && mod.__esModule) return mod; | ||
return result; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var fs = __importStar(require("fs")); | ||
var path = __importStar(require("path")); | ||
var pify_1 = __importDefault(require("pify")); | ||
var strip_json_comments_1 = __importDefault(require("strip-json-comments")); | ||
var fsReadFile = pify_1.default(fs.readFile); | ||
var CONFIG_FILE_NAME = 'js-green-licenses.json'; | ||
const fs = __importStar(require("fs")); | ||
const path = __importStar(require("path")); | ||
const strip_json_comments_1 = __importDefault(require("strip-json-comments")); | ||
const util_1 = require("util"); | ||
const fsReadFile = util_1.promisify(fs.readFile); | ||
const CONFIG_FILE_NAME = 'js-green-licenses.json'; | ||
function isConfig(obj) { | ||
var config = obj; | ||
var isStringArray = function (obj) { | ||
return !obj || | ||
(Array.isArray(obj) && obj.every(function (x) { return typeof x === 'string'; })); | ||
const config = obj; | ||
const isStringArray = (obj) => { | ||
return (!obj || (Array.isArray(obj) && obj.every(x => typeof x === 'string'))); | ||
}; | ||
return isStringArray(config.greenLicenses) && | ||
isStringArray(config.packageWhitelist); | ||
return (isStringArray(config.greenLicenses) && | ||
isStringArray(config.packageWhitelist)); | ||
} | ||
@@ -87,49 +51,29 @@ function ensureConfig(obj) { | ||
} | ||
function getLocalConfig(directory) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var content, err_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 3]); | ||
return [4 /*yield*/, fsReadFile(path.join(directory, CONFIG_FILE_NAME), 'utf8')]; | ||
case 1: | ||
content = _a.sent(); | ||
return [2 /*return*/, ensureConfig(parseJson(content))]; | ||
case 2: | ||
err_1 = _a.sent(); | ||
if (err_1.code !== 'ENOENT') { | ||
console.error('[js-green-licenses] Error while reading config file:', err_1); | ||
} | ||
return [2 /*return*/, null]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function getLocalConfig(directory) { | ||
try { | ||
const content = await fsReadFile(path.join(directory, CONFIG_FILE_NAME), 'utf8'); | ||
return ensureConfig(parseJson(content)); | ||
} | ||
catch (err) { | ||
if (err.code !== 'ENOENT') { | ||
console.error('[js-green-licenses] Error while reading config file:', err); | ||
} | ||
return null; | ||
} | ||
} | ||
exports.getLocalConfig = getLocalConfig; | ||
function getGitHubConfig(repo, commitSha) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var content; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, repo.getFileContent(commitSha, CONFIG_FILE_NAME)]; | ||
case 1: | ||
content = _a.sent(); | ||
if (!content) { | ||
return [2 /*return*/, null]; | ||
} | ||
try { | ||
return [2 /*return*/, ensureConfig(parseJson(content))]; | ||
} | ||
catch (err) { | ||
console.error('[js-green-licenses] Error while reading config file:', err); | ||
return [2 /*return*/, null]; | ||
} | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function getGitHubConfig(repo, commitSha) { | ||
const content = await repo.getFileContent(commitSha, CONFIG_FILE_NAME); | ||
if (!content) { | ||
return null; | ||
} | ||
try { | ||
return ensureConfig(parseJson(content)); | ||
} | ||
catch (err) { | ||
console.error('[js-green-licenses] Error while reading config file:', err); | ||
return null; | ||
} | ||
} | ||
exports.getGitHubConfig = getGitHubConfig; | ||
//# sourceMappingURL=config.js.map |
@@ -14,5 +14,5 @@ export interface PRCommits { | ||
constructor(owner: string, repo: string); | ||
private getAxiosConfig(authToken?); | ||
private apiGet(path, params?); | ||
private apiPost(path, body?); | ||
private getAxiosConfig; | ||
private apiGet; | ||
private apiPost; | ||
getPRCommits(prId: number, attemptCount?: number): Promise<PRCommits>; | ||
@@ -22,4 +22,4 @@ createPRReview(prId: number, commitSha: string, body: string): Promise<void>; | ||
getFileContent(commitSha: string, path: string): Promise<string | null>; | ||
private getSinglePackageJson(dir, commitSha); | ||
private getSinglePackageJson; | ||
getPackageJsonFiles(commitSha: string): Promise<PackageJsonFile[]>; | ||
} |
@@ -15,46 +15,8 @@ "use strict"; | ||
// limitations under the License. | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [0, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
// Abstractions over GitHub REST API v3 and related features. For GitHub API, | ||
// see https://developer.github.com/v3/. | ||
var axios_1 = __importDefault(require("axios")); | ||
var path_1 = require("path"); | ||
var url_1 = require("url"); | ||
const gaxios_1 = require("gaxios"); | ||
const path_1 = require("path"); | ||
const url_1 = require("url"); | ||
function isSingleResponseData(respData) { | ||
@@ -69,211 +31,127 @@ return !Array.isArray(respData); | ||
} | ||
var GitHubRepository = /** @class */ (function () { | ||
function GitHubRepository(owner, repo) { | ||
class GitHubRepository { | ||
constructor(owner, repo) { | ||
this.pathPrefix = path_1.posix.join('/repos', owner, repo); | ||
} | ||
GitHubRepository.prototype.getAxiosConfig = function (authToken) { | ||
return authToken ? { headers: { 'Authorization': "token " + authToken } } : {}; | ||
}; | ||
GitHubRepository.prototype.apiGet = function (path, params) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var url, resp; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
url = url_1.parse('https://api.github.com', true); | ||
url.pathname = path_1.posix.join(this.pathPrefix, path); | ||
if (params) { | ||
url.query = params; | ||
} | ||
return [4 /*yield*/, axios_1.default.get(url_1.format(url), this.getAxiosConfig())]; | ||
case 1: | ||
resp = _a.sent(); | ||
return [2 /*return*/, resp.data]; | ||
} | ||
getAxiosConfig(authToken) { | ||
return authToken | ||
? { headers: { Authorization: `token ${authToken}` } } | ||
: {}; | ||
} | ||
async apiGet(path, params) { | ||
const url = url_1.parse('https://api.github.com', true); | ||
url.pathname = path_1.posix.join(this.pathPrefix, path); | ||
if (params) { | ||
url.query = params; | ||
} | ||
const resp = await gaxios_1.request(Object.assign({ method: 'GET', url: url_1.format(url) }, this.getAxiosConfig())); | ||
return resp.data; | ||
} | ||
async apiPost(path, body) { | ||
const url = url_1.parse('https://api.github.com'); | ||
url.pathname = path_1.posix.join(this.pathPrefix, path); | ||
const resp = await gaxios_1.request(Object.assign({ method: 'POST', url: url_1.format(url), data: body }, this.getAxiosConfig())); | ||
return resp.data; | ||
} | ||
async getPRCommits(prId, attemptCount = 1) { | ||
let answer = await this.apiGet(path_1.posix.join('pulls', prId.toString())); | ||
answer = ensureSingleResponseData(answer); | ||
if (answer.mergeable == null) { | ||
if (attemptCount > GitHubRepository.MAX_PR_COMMIT_RETRIES) { | ||
throw new Error(`Tried ${attemptCount} times but the mergeable field is not set. Giving up`); | ||
} | ||
console.log('The `mergeable` field is not set yet. Will retry later.'); | ||
return new Promise(resolve => { | ||
setTimeout(async () => { | ||
resolve(await this.getPRCommits(prId, attemptCount + 1)); | ||
}, 1000); | ||
}); | ||
} | ||
else if (!answer.mergeable) { | ||
throw new Error('PR is not mergeable'); | ||
} | ||
const mergeCommitSha = answer.merge_commit_sha; | ||
if (!mergeCommitSha) { | ||
throw new Error('Merge commit SHA is not found'); | ||
} | ||
const headCommitSha = answer.head && answer.head.sha; | ||
if (!headCommitSha) { | ||
throw new Error('HEAD commit SHA is not found'); | ||
} | ||
return { mergeCommitSha, headCommitSha }; | ||
} | ||
async createPRReview(prId, commitSha, body) { | ||
await this.apiPost(path_1.posix.join('pulls', prId.toString(), 'reviews'), { | ||
commit_id: commitSha, | ||
body, | ||
event: 'COMMENT', | ||
}); | ||
}; | ||
GitHubRepository.prototype.apiPost = function (path, body) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var url, resp; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
url = url_1.parse('https://api.github.com'); | ||
url.pathname = path_1.posix.join(this.pathPrefix, path); | ||
return [4 /*yield*/, axios_1.default.post(url_1.format(url), body, this.getAxiosConfig())]; | ||
case 1: | ||
resp = _a.sent(); | ||
return [2 /*return*/, resp.data]; | ||
} | ||
}); | ||
} | ||
async setCommitStatus(commitSha, status, description, context) { | ||
await this.apiPost(path_1.posix.join('statuses', commitSha), { | ||
state: status, | ||
description, | ||
context, | ||
}); | ||
}; | ||
GitHubRepository.prototype.getPRCommits = function (prId, attemptCount) { | ||
if (attemptCount === void 0) { attemptCount = 1; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _this = this; | ||
var answer, mergeCommitSha, headCommitSha; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.apiGet(path_1.posix.join('pulls', prId.toString()))]; | ||
case 1: | ||
answer = _a.sent(); | ||
answer = ensureSingleResponseData(answer); | ||
if (answer.mergeable == null) { | ||
if (attemptCount > GitHubRepository.MAX_PR_COMMIT_RETRIES) { | ||
throw new Error("Tried " + attemptCount + " times but the mergeable field is not set. Giving up"); | ||
} | ||
console.log('The `mergeable` field is not set yet. Will retry later.'); | ||
return [2 /*return*/, new Promise(function (resolve) { | ||
setTimeout(function () { return __awaiter(_this, void 0, void 0, function () { | ||
var _a; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_a = resolve; | ||
return [4 /*yield*/, this.getPRCommits(prId, attemptCount + 1)]; | ||
case 1: | ||
_a.apply(void 0, [_b.sent()]); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }, 1000); | ||
})]; | ||
} | ||
else if (!answer.mergeable) { | ||
throw new Error('PR is not mergeable'); | ||
} | ||
mergeCommitSha = answer.merge_commit_sha; | ||
if (!mergeCommitSha) { | ||
throw new Error('Merge commit SHA is not found'); | ||
} | ||
headCommitSha = answer.head && answer.head.sha; | ||
if (!headCommitSha) { | ||
throw new Error('HEAD commit SHA is not found'); | ||
} | ||
return [2 /*return*/, { mergeCommitSha: mergeCommitSha, headCommitSha: headCommitSha }]; | ||
} | ||
} | ||
async getFileContent(commitSha, path) { | ||
let answer; | ||
try { | ||
answer = await this.apiGet(path_1.posix.join('contents', path), { | ||
ref: commitSha, | ||
}); | ||
}); | ||
}; | ||
GitHubRepository.prototype.createPRReview = function (prId, commitSha, body) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.apiPost(path_1.posix.join('pulls', prId.toString(), 'reviews'), { commit_id: commitSha, body: body, event: 'COMMENT' })]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
catch (_a) { | ||
return null; | ||
} | ||
answer = ensureSingleResponseData(answer); | ||
if (answer.content === undefined) { | ||
throw new Error(`Content of ${path} not found`); | ||
} | ||
const content = Buffer.from(answer.content, 'base64').toString(); | ||
return content; | ||
} | ||
async getSinglePackageJson(dir, commitSha) { | ||
const content = await this.getFileContent(commitSha, path_1.posix.join(dir, 'package.json')); | ||
if (!content) { | ||
return null; | ||
} | ||
const filePath = path_1.posix.join('/', dir, 'package.json'); | ||
return { filePath, content }; | ||
} | ||
async getPackageJsonFiles(commitSha) { | ||
const packageJsons = []; | ||
// Find the top-level package.json first. | ||
const pj = await this.getSinglePackageJson('', commitSha); | ||
if (pj !== null) { | ||
packageJsons.push(pj); | ||
} | ||
// Find `packages/<name>/package.json` files in case this is a monorepo. | ||
let answer; | ||
try { | ||
answer = await this.apiGet('contents/packages', { ref: commitSha }); | ||
} | ||
catch (_a) { | ||
// Not a monorepo. Return just the top-level package.json. | ||
return packageJsons; | ||
} | ||
if (!isSingleResponseData(answer)) { | ||
// Response is an array, which means there's the `packages` directory and | ||
// this is a monorepo. Find package.json from each directory under | ||
// `packages`. | ||
for (const entry of answer) { | ||
if (entry.type === 'dir' && entry.name) { | ||
const pj = await this.getSinglePackageJson(path_1.posix.join('packages', entry.name), commitSha); | ||
if (pj !== null) { | ||
packageJsons.push(pj); | ||
} | ||
} | ||
}); | ||
}); | ||
}; | ||
GitHubRepository.prototype.setCommitStatus = function (commitSha, status, description, context) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.apiPost(path_1.posix.join('statuses', commitSha), { state: status, description: description, context: context })]; | ||
case 1: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
GitHubRepository.prototype.getFileContent = function (commitSha, path) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var answer, _a, content; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
_b.trys.push([0, 2, , 3]); | ||
return [4 /*yield*/, this.apiGet(path_1.posix.join('contents', path), { ref: commitSha })]; | ||
case 1: | ||
answer = | ||
_b.sent(); | ||
return [3 /*break*/, 3]; | ||
case 2: | ||
_a = _b.sent(); | ||
return [2 /*return*/, null]; | ||
case 3: | ||
answer = ensureSingleResponseData(answer); | ||
if (answer.content === undefined) { | ||
throw new Error("Content of " + path + " not found"); | ||
} | ||
content = Buffer.from(answer.content, 'base64').toString(); | ||
return [2 /*return*/, content]; | ||
} | ||
}); | ||
}); | ||
}; | ||
GitHubRepository.prototype.getSinglePackageJson = function (dir, commitSha) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var content, filePath; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, this.getFileContent(commitSha, path_1.posix.join(dir, 'package.json'))]; | ||
case 1: | ||
content = _a.sent(); | ||
if (!content) { | ||
return [2 /*return*/, null]; | ||
} | ||
filePath = path_1.posix.join('/', dir, 'package.json'); | ||
return [2 /*return*/, { filePath: filePath, content: content }]; | ||
} | ||
}); | ||
}); | ||
}; | ||
GitHubRepository.prototype.getPackageJsonFiles = function (commitSha) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var packageJsons, pj, answer, _a, _i, answer_1, entry, pj_1; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
packageJsons = []; | ||
return [4 /*yield*/, this.getSinglePackageJson('', commitSha)]; | ||
case 1: | ||
pj = _b.sent(); | ||
if (pj !== null) { | ||
packageJsons.push(pj); | ||
} | ||
_b.label = 2; | ||
case 2: | ||
_b.trys.push([2, 4, , 5]); | ||
return [4 /*yield*/, this.apiGet('contents/packages', { ref: commitSha })]; | ||
case 3: | ||
answer = _b.sent(); | ||
return [3 /*break*/, 5]; | ||
case 4: | ||
_a = _b.sent(); | ||
// Not a monorepo. Return just the top-level package.json. | ||
return [2 /*return*/, packageJsons]; | ||
case 5: | ||
if (!!isSingleResponseData(answer)) return [3 /*break*/, 9]; | ||
_i = 0, answer_1 = answer; | ||
_b.label = 6; | ||
case 6: | ||
if (!(_i < answer_1.length)) return [3 /*break*/, 9]; | ||
entry = answer_1[_i]; | ||
if (!(entry.type === 'dir' && entry.name)) return [3 /*break*/, 8]; | ||
return [4 /*yield*/, this.getSinglePackageJson(path_1.posix.join('packages', entry.name), commitSha)]; | ||
case 7: | ||
pj_1 = _b.sent(); | ||
if (pj_1 !== null) { | ||
packageJsons.push(pj_1); | ||
} | ||
_b.label = 8; | ||
case 8: | ||
_i++; | ||
return [3 /*break*/, 6]; | ||
case 9: return [2 /*return*/, packageJsons]; | ||
} | ||
}); | ||
}); | ||
}; | ||
// How many times to retry PR commit retrieval until giving up. | ||
GitHubRepository.MAX_PR_COMMIT_RETRIES = 10; | ||
return GitHubRepository; | ||
}()); | ||
} | ||
} | ||
return packageJsons; | ||
} | ||
} | ||
// How many times to retry PR commit retrieval until giving up. | ||
GitHubRepository.MAX_PR_COMMIT_RETRIES = 10; | ||
exports.GitHubRepository = GitHubRepository; | ||
//# sourceMappingURL=github.js.map |
@@ -12,2 +12,3 @@ export interface OldLicenseField { | ||
version: string; | ||
private?: boolean; | ||
license?: License; | ||
@@ -14,0 +15,0 @@ licenses?: License; |
@@ -16,15 +16,16 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var util_1 = require("util"); | ||
const util_1 = require("util"); | ||
function isOldLicenseField(obj) { | ||
var field = obj; | ||
return typeof field.type === 'string' && | ||
(field.url === undefined || typeof field.url === 'string'); | ||
const field = obj; | ||
return (typeof field.type === 'string' && | ||
(field.url === undefined || typeof field.url === 'string')); | ||
} | ||
function isLicense(obj) { | ||
return typeof obj === 'string' || isOldLicenseField(obj) || | ||
(Array.isArray(obj) && obj.every(isOldLicenseField)); | ||
return (typeof obj === 'string' || | ||
isOldLicenseField(obj) || | ||
(Array.isArray(obj) && obj.every(isOldLicenseField))); | ||
} | ||
// tslint:disable-next-line:no-any `obj` is from JSON and can be any. | ||
function isDependencies(obj) { | ||
for (var key in obj) { | ||
for (const key in obj) { | ||
if (obj.hasOwnProperty(key) && typeof obj[key] !== 'string') { | ||
@@ -37,13 +38,15 @@ return false; | ||
function isPackageJson(obj) { | ||
var json = obj; | ||
return typeof json.name === 'string' && typeof json.version === 'string' && | ||
(json.license === undefined || isLicense(json.license)) && | ||
(json.licenses === undefined || isLicense(json.licenses)) && | ||
(json.dependencies === undefined || isDependencies(json.dependencies)) && | ||
(json.devDependencies === undefined || | ||
isDependencies(json.devDependencies)); | ||
const json = obj; | ||
return ((typeof json.private === 'boolean' && json.private) || | ||
(typeof json.name === 'string' && | ||
typeof json.version === 'string' && | ||
(json.license === undefined || isLicense(json.license)) && | ||
(json.licenses === undefined || isLicense(json.licenses)) && | ||
(json.dependencies === undefined || isDependencies(json.dependencies)) && | ||
(json.devDependencies === undefined || | ||
isDependencies(json.devDependencies)))); | ||
} | ||
function ensurePackageJson(obj) { | ||
if (!isPackageJson(obj)) { | ||
throw new Error("Invalid package.json: " + util_1.inspect(obj)); | ||
throw new Error(`Invalid package.json: ${util_1.inspect(obj)}`); | ||
} | ||
@@ -50,0 +53,0 @@ return obj; |
{ | ||
"name": "js-green-licenses", | ||
"version": "0.5.0", | ||
"version": "1.0.0", | ||
"description": "JavaScript package.json license checker", | ||
@@ -29,2 +29,5 @@ "main": "build/src/checker.js", | ||
}, | ||
"engines": { | ||
"node": ">= 8.x" | ||
}, | ||
"keywords": [ | ||
@@ -49,19 +52,16 @@ "npm", | ||
"dependencies": { | ||
"argparse": "^1.0.9", | ||
"axios": "^0.18.0", | ||
"npm-package-arg": "^6.0.0", | ||
"package-json": "^4.0.1", | ||
"pify": "^3.0.0", | ||
"argparse": "^1.0.10", | ||
"gaxios": "^2.0.1", | ||
"npm-package-arg": "^6.1.0", | ||
"package-json": "^6.0.0", | ||
"spdx-correct": "^3.0.0", | ||
"spdx-satisfies": "^4.0.0", | ||
"strip-json-comments": "^2.0.1" | ||
"spdx-satisfies": "^5.0.0", | ||
"strip-json-comments": "^3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/argparse": "^1.0.33", | ||
"@types/mock-fs": "^3.6.30", | ||
"@types/nock": "^9.1.1", | ||
"@types/node": "^9.3.0", | ||
"@types/npm-package-arg": "^5.1.0", | ||
"@types/package-json": "^4.0.1", | ||
"@types/pify": "^3.0.0", | ||
"@types/nock": "^10.0.0", | ||
"@types/node": "^10.0.1", | ||
"@types/npm-package-arg": "^6.0.0", | ||
"@types/package-json": "^5.0.0", | ||
"@types/proxyquire": "^1.3.28", | ||
@@ -71,11 +71,14 @@ "@types/spdx-correct": "^2.0.0", | ||
"@types/strip-json-comments": "0.0.30", | ||
"ava": "^0.25.0", | ||
"codecov": "^3.0.0", | ||
"gts": "^0.5.3", | ||
"@types/tmp": "0.1.0", | ||
"ava": "^1.0.0", | ||
"codecov": "^3.0.1", | ||
"gts": "^1.0.0", | ||
"make-dir": "^3.0.0", | ||
"mock-fs": "^4.4.2", | ||
"nock": "^9.1.6", | ||
"nyc": "^11.4.1", | ||
"proxyquire": "^2.0.0", | ||
"typescript": "~2.7.1" | ||
"nock": "^10.0.0", | ||
"nyc": "^14.0.0", | ||
"proxyquire": "^2.0.1", | ||
"tmp": "0.1.0", | ||
"typescript": "~3.4.0" | ||
} | ||
} |
@@ -6,6 +6,5 @@ # JavaScript package.json License Checker | ||
[![Dependency Status][david-image]][david-url] | ||
[![devDependency Status][david-dev-image]][david-dev-url] | ||
[![Known Vulnerabilities][snyk-image]][snyk-url] | ||
[![codecov][codecov-image]][codecov-url] | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/google/js-green-licenses.svg)](https://greenkeeper.io/) | ||
[![Code Style: Google][gts-image]][gts-url] | ||
@@ -313,10 +312,10 @@ **This is not an official Google product.** | ||
[circle-image]: https://circleci.com/gh/google/js-green-licenses.svg?style=svg | ||
[circle-image]: https://circleci.com/gh/google/js-green-licenses.svg?style=shield | ||
[circle-url]: https://circleci.com/gh/google/js-green-licenses | ||
[codecov-image]: https://codecov.io/gh/google/js-green-licenses/branch/master/graph/badge.svg | ||
[codecov-url]: https://codecov.io/gh/google/js-green-licenses | ||
[david-dev-image]: https://david-dm.org/google/js-green-licenses/dev-status.svg | ||
[david-dev-url]: https://david-dm.org/google/js-green-licenses?type=dev | ||
[david-image]: https://david-dm.org/google/js-green-licenses.svg | ||
[david-url]: https://david-dm.org/google/js-green-licenses | ||
[gts-image]: https://img.shields.io/badge/code%20style-google-blueviolet.svg | ||
[gts-url]: https://github.com/google/gts | ||
[npm-image]: https://img.shields.io/npm/v/js-green-licenses.svg | ||
@@ -323,0 +322,0 @@ [npm-url]: https://npmjs.org/package/js-green-licenses |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
7
20
1
81746
20
866
323
2
+ Addedgaxios@^2.0.1
+ Added@sindresorhus/is@0.14.0(transitive)
+ Added@szmarczak/http-timer@1.1.2(transitive)
+ Addedabort-controller@3.0.0(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedcacheable-request@6.1.0(transitive)
+ Addedclone-response@1.0.3(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddecompress-response@3.3.0(transitive)
+ Addeddefer-to-connect@1.1.3(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedevent-target-shim@5.0.1(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedgaxios@2.3.4(transitive)
+ Addedget-stream@4.1.05.2.0(transitive)
+ Addedgot@9.6.0(transitive)
+ Addedhttp-cache-semantics@4.1.1(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedis-stream@2.0.1(transitive)
+ Addedjson-buffer@3.0.0(transitive)
+ Addedkeyv@3.1.0(transitive)
+ Addedlowercase-keys@2.0.0(transitive)
+ Addedmimic-response@1.0.1(transitive)
+ Addedms@2.1.3(transitive)
+ Addednode-fetch@2.7.0(transitive)
+ Addednormalize-url@4.5.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedp-cancelable@1.1.0(transitive)
+ Addedpackage-json@6.5.0(transitive)
+ Addedprepend-http@2.0.0(transitive)
+ Addedpump@3.0.2(transitive)
+ Addedregistry-auth-token@4.2.2(transitive)
+ Addedregistry-url@5.1.0(transitive)
+ Addedresponselike@1.0.2(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedspdx-satisfies@5.0.1(transitive)
+ Addedstrip-json-comments@3.1.1(transitive)
+ Addedto-readable-stream@1.0.0(transitive)
+ Addedtr46@0.0.3(transitive)
+ Addedurl-parse-lax@3.0.0(transitive)
+ Addedwebidl-conversions@3.0.1(transitive)
+ Addedwhatwg-url@5.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removedaxios@^0.18.0
- Removedpify@^3.0.0
- Removedaxios@0.18.1(transitive)
- Removedcapture-stack-trace@1.0.2(transitive)
- Removedcreate-error-class@3.0.2(transitive)
- Removedfollow-redirects@1.5.10(transitive)
- Removedget-stream@3.0.0(transitive)
- Removedgot@6.7.1(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedis-redirect@1.0.0(transitive)
- Removedis-retry-allowed@1.2.0(transitive)
- Removedis-stream@1.1.0(transitive)
- Removedpackage-json@4.0.1(transitive)
- Removedpify@3.0.0(transitive)
- Removedprepend-http@1.0.4(transitive)
- Removedregistry-auth-token@3.4.0(transitive)
- Removedregistry-url@3.1.0(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedspdx-satisfies@4.0.1(transitive)
- Removedtimed-out@4.0.1(transitive)
- Removedunzip-response@2.0.1(transitive)
- Removedurl-parse-lax@1.0.0(transitive)
Updatedargparse@^1.0.10
Updatednpm-package-arg@^6.1.0
Updatedpackage-json@^6.0.0
Updatedspdx-satisfies@^5.0.0
Updatedstrip-json-comments@^3.0.0