"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dp = require("dependency-path");
const shrinkwrap_1 = require("../fs/shrinkwrap");
const pnpm_shrinkwrap_1 = require("pnpm-shrinkwrap");
const R = require("ramda");
function default_1(pkgsToLink, shrinkwrap, pkg) {
    shrinkwrap.packages = shrinkwrap.packages || {};
    for (const dependencyAbsolutePath of R.keys(pkgsToLink)) {
        const dependencyPath = dp.relative(shrinkwrap.registry, dependencyAbsolutePath);
        const result = R.partition((childResolvedId) => pkgsToLink[dependencyAbsolutePath].optionalDependencies.has(pkgsToLink[childResolvedId].name), pkgsToLink[dependencyAbsolutePath].children);
        shrinkwrap.packages[dependencyPath] = toShrDependency(pkgsToLink[dependencyAbsolutePath].pkg, {
            dependencyAbsolutePath,
            name: pkgsToLink[dependencyAbsolutePath].name,
            version: pkgsToLink[dependencyAbsolutePath].version,
            id: pkgsToLink[dependencyAbsolutePath].id,
            dependencyPath,
            resolution: pkgsToLink[dependencyAbsolutePath].resolution,
            updatedOptionalDeps: result[0],
            updatedDeps: result[1],
            registry: shrinkwrap.registry,
            pkgsToLink,
            prevResolvedDeps: shrinkwrap.packages[dependencyPath] && shrinkwrap.packages[dependencyPath].dependencies || {},
            prevResolvedOptionalDeps: shrinkwrap.packages[dependencyPath] && shrinkwrap.packages[dependencyPath].optionalDependencies || {},
            prod: pkgsToLink[dependencyAbsolutePath].prod,
            dev: pkgsToLink[dependencyAbsolutePath].dev,
            optional: pkgsToLink[dependencyAbsolutePath].optional,
        });
    }
    return pnpm_shrinkwrap_1.prune(shrinkwrap, pkg);
}
exports.default = default_1;
function toShrDependency(pkg, opts) {
    const shrResolution = toShrResolution(opts.dependencyPath, opts.resolution, opts.registry);
    const newResolvedDeps = updateResolvedDeps(opts.prevResolvedDeps, opts.updatedDeps, opts.registry, opts.pkgsToLink);
    const newResolvedOptionalDeps = updateResolvedDeps(opts.prevResolvedOptionalDeps, opts.updatedOptionalDeps, opts.registry, opts.pkgsToLink);
    const result = {
        resolution: shrResolution
    };
    if (dp.isAbsolute(opts.dependencyPath)) {
        result['name'] = opts.name;
        // There is no guarantee that a non-npmjs.org-hosted package
        // is going to have a version field
        if (opts.version) {
            result['version'] = opts.version;
        }
    }
    if (!R.isEmpty(newResolvedDeps)) {
        result['dependencies'] = newResolvedDeps;
    }
    if (!R.isEmpty(newResolvedOptionalDeps)) {
        result['optionalDependencies'] = newResolvedOptionalDeps;
    }
    if (opts.dev && !opts.prod) {
        result['dev'] = true;
    }
    else if (opts.prod && !opts.dev) {
        result['dev'] = false;
    }
    if (opts.optional) {
        result['optional'] = true;
    }
    if (opts.dependencyAbsolutePath !== opts.id) {
        result['id'] = opts.id;
    }
    if (pkg.peerDependencies) {
        const ownDeps = new Set(R.keys(pkg.dependencies).concat(R.keys(pkg.optionalDependencies)));
        for (let peer of R.keys(pkg.peerDependencies)) {
            if (ownDeps.has(peer))
                continue;
            result['peerDependencies'] = result['peerDependencies'] || {};
            result['peerDependencies'][peer] = pkg.peerDependencies[peer];
        }
    }
    if (pkg.engines) {
        for (let engine of R.keys(pkg.engines)) {
            if (pkg.engines[engine] === '*')
                continue;
            result['engines'] = result['engines'] || {};
            result['engines'][engine] = pkg.engines[engine];
        }
    }
    if (pkg.cpu) {
        result['cpu'] = pkg.cpu;
    }
    if (pkg.os) {
        result['os'] = pkg.os;
    }
    if (pkg.bundledDependencies || pkg.bundleDependencies) {
        result['bundledDependencies'] = pkg.bundledDependencies || pkg.bundleDependencies;
    }
    if (pkg.deprecated) {
        result['deprecated'] = pkg.deprecated;
    }
    return result;
}
// previous resolutions should not be removed from shrinkwrap
// as installation might not reanalize the whole dependency tree
// the `depth` property defines how deep should dependencies be checked
function updateResolvedDeps(prevResolvedDeps, updatedDeps, registry, pkgsToLink) {
    const newResolvedDeps = R.fromPairs(R.props(updatedDeps, pkgsToLink)
        .map((dep) => [
        dep.name,
        shrinkwrap_1.absolutePathToRef(dep.absolutePath, dep.name, dep.resolution, registry)
    ]));
    return R.merge(prevResolvedDeps, newResolvedDeps);
}
function toShrResolution(dependencyPath, resolution, registry) {
    if (dp.isAbsolute(dependencyPath) || resolution.type !== undefined || !resolution.integrity) {
        return resolution;
    }
    // This might be not the best solution to identify non-standard tarball URLs in the long run
    // but it at least solves the issues with npm Enterprise. See https://github.com/pnpm/pnpm/issues/867
    if (!resolution.tarball.includes('/-/')) {
        return {
            integrity: resolution.integrity,
            tarball: relativeTarball(resolution.tarball, registry),
        };
    }
    return {
        integrity: resolution.integrity,
    };
}
function relativeTarball(tarball, registry) {
    if (tarball.substr(0, registry.length) === registry) {
        return tarball.substr(registry.length - 1);
    }
    return tarball;
}
//# sourceMappingURL=updateShrinkwrap.js.map