report.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const app_1 = require("./app");
const counsel = require("counsel");
const logger_1 = require("./logger");
const resolveDeps = require('snyk-resolve-deps');
const uiBuild = require('./ui-build');
const _ = require('lodash');
const values = _.values;
const get = _.get;
function generate(action, opts) {
    const rptPkg = counsel.targetProjectPackageJson;
    /* istanbul ignore next */
    if (!rptPkg.name || !rptPkg.version) {
        throw new ReferenceError('package name and version required in package.json');
    }
    /* istanbul ignore next */
    if (!rptPkg.license)
        throw new ReferenceError('package requires a license in package.json');
    return getDependencies(opts)
        .then(deps => twFormat(rptPkg, deps));
}
exports.generate = generate;
/**
 * @export
 * @param {any} opts
 * @param {string} [opts.targetProjectRoot] project root to get dependencies from (defaults to counsel.targetProjectRoot)
 * @param {boolean} [opts.retainUnused]
 * @returns {Promise} Promise<IPkgSet>
 */
function getDependencies(opts) {
    opts = opts || {};
    const projectRoot = opts.targetProjectRoot || counsel.targetProjectRoot;
    const licenserConfig = {
        dev: true,
        extraFields: [app_1.pkgId, 'author', 'maintainer', 'maintainers']
    };
    const resDepsP = resolveDeps(projectRoot, licenserConfig);
    logger_1.default.verbose('getting logical dependencies');
    return Promise.resolve(resDepsP)
        .then(rootPkg => {
        handleSnykDepTypeBug({ pkgs: rootPkg.dependencies, root: true });
        return rootPkg.dependencies;
    })
        .then(pkgs => mapSnykPkgSetToPkgSet(pkgs))
        .then(pkgs => uiBuild.applyWebBuildTransform(pkgs, opts));
}
exports.getDependencies = getDependencies;
function getAuthorOrMaintainers(pkg) {
    let [author, mtn, mtns] = [get(pkg, 'author'), get(pkg, 'maintainer'), get(pkg, 'maintainers')];
    if (author) {
        if (typeof author === 'string')
            return author;
        let _author = `${author.name || 'UNKNOWN'}`;
        if (author.email)
            _author = `${_author}<${author.email}>`;
        return _author;
    }
    if (mtn)
        return mtn.name || mtn;
    if (Array.isArray(mtns)) {
        let names = [];
        mtns.forEach(mtn => {
            if (typeof mtn === 'string')
                names.push(mtn);
            if (mtn.name) {
                let _mtn = `${mtn.name}`;
                if (mtn.email)
                    _mtn = `${_mtn}<${mtn.email}>`;
                names.push(_mtn);
            }
        });
        return names.join('; ');
    }
    return '';
}
exports.getAuthorOrMaintainers = getAuthorOrMaintainers;
/**
 * see https://github.com/Snyk/resolve-deps/issues/28
 * @param {object} opts
 * @param {IPkgSet} opts.pkgs
 * @param {boolean} [opts.root]
 * @return {IPkgSet} pkgs
 */
function handleSnykDepTypeBug({ pkgs, root }) {
    _handleSnykDepTypeBugPrdWhitelist({ pkgs, root });
    _handleSnykDepTypeBugMarkDevDepsAsDev({ pkgs, root });
}
exports.handleSnykDepTypeBug = handleSnykDepTypeBug;
/**
 * traverse tree, marking all prd pkgs as prd, s.t. dev marker won't erroronesously flag as dev
 * @param {any} { pkgs, root }
 * @returns {object} pkgs
 */
function _handleSnykDepTypeBugPrdWhitelist({ pkgs, root }) {
    let _pkgs = values(pkgs || []);
    if (root)
        _pkgs = _pkgs.filter(pkg => pkg.depType.match(/prod/));
    _pkgs.forEach(pkg => {
        pkg.production = true;
        pkg.depType = 'prod';
        if (!pkg._syncDepTypeBugIsProd)
            _handleSnykDepTypeBugPrdWhitelist({ pkgs: pkg.dependencies, root: false });
        Object.defineProperty(pkg, '_syncDepTypeBugIsProd', { enumerable: false, writable: true, value: true });
    });
    return pkgs;
}
function _handleSnykDepTypeBugMarkDevDepsAsDev({ pkgs, root }) {
    let _pkgs = values(pkgs || []);
    if (root)
        _pkgs = _pkgs.filter(pkg => !pkg.depType.match(/prod/));
    _pkgs.forEach(pkg => {
        if (pkg._syncDepTypeBugIsProd)
            return;
        pkg.production = false;
        pkg.depType = 'dev';
        if (!pkg._syncDepTypeBugHandled)
            _handleSnykDepTypeBugMarkDevDepsAsDev({ pkgs: pkg.dependencies, root: false });
        Object.defineProperty(pkg, '_syncDepTypeBugHandled', { enumerable: false, writable: true, value: true });
    });
    return pkgs;
}
/**
 * mutates the snyk dep report in place to include only a small subset of keys for
 * noise reduction and ease of parsing for people interested in the report.
 * @private
 * @param {object} depSet snyk dep set
 * @returns {object}
 */
function mapSnykPkgSetToPkgSet(sSet) {
    let pSet = null;
    let pkgName;
    let pkg;
    let sPkg;
    let i = 0;
    if (!sSet || !Object.keys(sSet).length)
        return null;
    pSet = {};
    for (pkgName in sSet) {
        ++i;
        sPkg = sSet[pkgName];
        if (sPkg.depType === 'extraneous') { }
        else {
            const dSet = mapSnykPkgSetToPkgSet(sPkg.dependencies);
            // ^^ .dependencies _has_ deps and devDeps
            pkg = {
                author: getAuthorOrMaintainers(sPkg),
                from: sPkg.from,
                dependencies: dSet,
                license: sPkg.license,
                licenses: [sPkg.license],
                name: sPkg.name,
                production: !!sPkg.depType.match(/prod/),
                [app_1.pkgId]: sPkg[app_1.pkgId] || '',
                requestedVersion: sPkg.dep || '',
                version: sPkg.version
            };
            pSet[pkgName] = pkg;
        }
    }
    return pSet || null;
}
exports.mapSnykPkgSetToPkgSet = mapSnykPkgSetToPkgSet;
/**
 * apply formatting to snyk deps
 * @param {object} deps snyk deps
 * @returns {object} deps
 */
function twFormat(rptPkg, deps) {
    const prd = {};
    const dev = {};
    for (let pkgName in deps) {
        let pkg = deps[pkgName];
        if (pkg.production)
            prd[pkgName] = pkg;
        else
            dev[pkgName] = pkg;
    }
    return {
        package: {
            author: getAuthorOrMaintainers(rptPkg),
            name: rptPkg.name,
            version: rptPkg.version,
            license: rptPkg.license
        },
        configurations: {
            compile: prd,
            testCompile: dev
        }
    };
}
//# sourceMappingURL=report.js.map