"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dp = require("dependency-path");
const R = require("ramda");
const logger_1 = require("./logger");
function filterByImporters(shr, importerIds, opts) {
    if (R.equals(importerIds.sort(), R.keys(shr.importers).sort())) {
        return filterShrinkwrap(shr, opts);
    }
    const importerDeps = importerIds
        .map((importerId) => shr.importers[importerId])
        .map((importer) => (Object.assign({}, (opts.include.dependencies && importer.dependencies || {}), (opts.include.devDependencies && importer.devDependencies || {}), (opts.include.optionalDependencies && importer.optionalDependencies || {}))))
        .map(R.toPairs);
    const directDepPaths = R.unnest(importerDeps)
        .map(([pkgName, ref]) => dp.refToRelative(ref, pkgName))
        .filter((nodeId) => nodeId !== null);
    const packages = shr.packages &&
        pickPkgsWithAllDeps(shr.packages, directDepPaths, {
            failOnMissingDependencies: opts.failOnMissingDependencies,
            include: opts.include,
        }) || {};
    const importers = importerIds.reduce((acc, importerId) => {
        acc[importerId] = filterImporter(shr.importers[importerId], opts.include);
        return acc;
    }, Object.assign({}, shr.importers));
    return normalizeShrinkwrap({
        importers,
        packages,
        registry: shr.registry,
        shrinkwrapVersion: shr.shrinkwrapVersion,
    });
}
exports.filterByImporters = filterByImporters;
function filterShrinkwrap(shr, opts) {
    let pairs = R.toPairs(shr.packages || {})
        .filter(([relDepPath, pkg]) => !opts.skipped.has(pkg.id || dp.resolve(opts.defaultRegistry, relDepPath)));
    if (!opts.include.dependencies) {
        pairs = pairs.filter(([relDepPath, pkg]) => pkg.dev !== false || pkg.optional);
    }
    if (!opts.include.devDependencies) {
        pairs = pairs.filter(([relDepPath, pkg]) => pkg.dev !== true);
    }
    if (!opts.include.optionalDependencies) {
        pairs = pairs.filter(([relDepPath, pkg]) => !pkg.optional);
    }
    return normalizeShrinkwrap({
        importers: Object.keys(shr.importers).reduce((acc, importerId) => {
            acc[importerId] = filterImporter(shr.importers[importerId], opts.include);
            return acc;
        }, {}),
        packages: R.fromPairs(pairs),
        registry: shr.registry,
        shrinkwrapVersion: shr.shrinkwrapVersion,
    });
}
exports.default = filterShrinkwrap;
function normalizeShrinkwrap(shr) {
    if (!shr.registry) {
        delete shr.registry;
    }
    return shr;
}
function pickPkgsWithAllDeps(pkgSnapshots, relDepPaths, opts) {
    const pickedPackages = {};
    pkgAllDeps(pkgSnapshots, pickedPackages, relDepPaths, opts);
    return pickedPackages;
}
function pkgAllDeps(pkgSnapshots, pickedPackages, relDepPaths, opts) {
    for (const relDepPath of relDepPaths) {
        if (pickedPackages[relDepPath])
            continue;
        const pkgSnapshot = pkgSnapshots[relDepPath];
        if (!pkgSnapshot && !relDepPath.startsWith('link:')) {
            const message = `No entry for "${relDepPath}" in shrinkwrap.yaml`;
            if (opts.failOnMissingDependencies) {
                const err = new Error(message);
                err['code'] = 'ERR_PNPM_SHRINKWRAP_MISSING_DEPENDENCY'; // tslint:disable-line:no-string-literal
                throw err;
            }
            logger_1.default.debug(message);
            continue;
        }
        pickedPackages[relDepPath] = pkgSnapshot;
        const nextRelDepPaths = R.toPairs(Object.assign({}, pkgSnapshot.dependencies, (opts.include.optionalDependencies && pkgSnapshot.optionalDependencies || {})))
            .map(([pkgName, ref]) => dp.refToRelative(ref, pkgName))
            .filter((nodeId) => nodeId !== null);
        pkgAllDeps(pkgSnapshots, pickedPackages, nextRelDepPaths, opts);
    }
}
function filterImporter(importer, include) {
    return {
        dependencies: !include.dependencies ? {} : importer.dependencies || {},
        devDependencies: !include.devDependencies ? {} : importer.devDependencies || {},
        optionalDependencies: !include.optionalDependencies ? {} : importer.optionalDependencies || {},
        specifiers: importer.specifiers,
    };
}
//# sourceMappingURL=filter.js.map