"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
const R = require("ramda");
const nodeIdUtils_1 = require("./nodeIdUtils");
const resolveDependencies_1 = require("./resolveDependencies");
__exportStar(require("./nodeIdUtils"), exports);
async function default_1(importers, opts) {
    var _a;
    const directDepsByImporterId = {};
    const wantedToBeSkippedPackageIds = new Set();
    const ctx = {
        childrenByParentId: {},
        currentLockfile: opts.currentLockfile,
        defaultTag: opts.tag,
        dependenciesTree: {},
        dryRun: opts.dryRun,
        engineStrict: opts.engineStrict,
        force: opts.force,
        forceFullResolution: opts.forceFullResolution,
        linkWorkspacePackagesDepth: (_a = opts.linkWorkspacePackagesDepth) !== null && _a !== void 0 ? _a : -1,
        lockfileDir: opts.lockfileDir,
        nodeVersion: opts.nodeVersion,
        outdatedDependencies: {},
        pendingNodes: [],
        pnpmVersion: opts.pnpmVersion,
        readPackageHook: opts.hooks.readPackage,
        registries: opts.registries,
        resolvedPackagesByPackageId: {},
        skipped: wantedToBeSkippedPackageIds,
        storeController: opts.storeController,
        virtualStoreDir: opts.virtualStoreDir,
        wantedLockfile: opts.wantedLockfile,
    };
    await Promise.all(importers.map(async (importer) => {
        var _a;
        const projectSnapshot = opts.wantedLockfile.importers[importer.id];
        // This array will only contain the dependencies that should be linked in.
        // The already linked-in dependencies will not be added.
        const linkedDependencies = [];
        const resolveCtx = {
            ...ctx,
            linkedDependencies,
            modulesDir: importer.modulesDir,
            prefix: importer.rootDir,
        };
        // This may be optimized.
        // We only need to proceed resolving every dependency
        // if the newly added dependency has peer dependencies.
        const proceed = importer.hasRemovedDependencies || importer.wantedDependencies.some((wantedDep) => wantedDep['isNew']);
        const resolveOpts = {
            alwaysTryWorkspacePackages: ((_a = opts.linkWorkspacePackagesDepth) !== null && _a !== void 0 ? _a : -1) >= 0,
            currentDepth: 0,
            parentDependsOnPeers: proceed,
            parentNodeId: `>${importer.id}>`,
            preferredVersions: importer.preferredVersions || {},
            proceed,
            resolvedDependencies: {
                ...projectSnapshot.dependencies,
                ...projectSnapshot.devDependencies,
                ...projectSnapshot.optionalDependencies,
            },
            updateDepth: -1,
            workspacePackages: opts.workspacePackages,
        };
        directDepsByImporterId[importer.id] = await resolveDependencies_1.default(resolveCtx, importer.wantedDependencies, resolveOpts);
    }));
    ctx.pendingNodes.forEach((pendingNode) => {
        ctx.dependenciesTree[pendingNode.nodeId] = {
            children: () => buildTree(ctx, pendingNode.nodeId, pendingNode.resolvedPackage.id, ctx.childrenByParentId[pendingNode.resolvedPackage.id], pendingNode.depth + 1, pendingNode.installable),
            depth: pendingNode.depth,
            installable: pendingNode.installable,
            resolvedPackage: pendingNode.resolvedPackage,
        };
    });
    const resolvedImporters = {};
    for (const { id } of importers) {
        const directDeps = directDepsByImporterId[id];
        const [linkedDependencies, directNonLinkedDeps] = R.partition((dep) => dep.isLinkedDependency === true, directDeps);
        resolvedImporters[id] = {
            directDependencies: directDeps
                .map((dep) => {
                if (dep.isLinkedDependency === true) {
                    return dep;
                }
                const resolvedPackage = ctx.dependenciesTree[dep.nodeId].resolvedPackage;
                return {
                    alias: dep.alias,
                    dev: resolvedPackage.dev,
                    name: resolvedPackage.name,
                    normalizedPref: dep.normalizedPref,
                    optional: resolvedPackage.optional,
                    pkgId: resolvedPackage.id,
                    resolution: resolvedPackage.resolution,
                    version: resolvedPackage.version,
                };
            }),
            directNodeIdsByAlias: directNonLinkedDeps
                .reduce((acc, dependency) => {
                acc[dependency.alias] = dependency.nodeId;
                return acc;
            }, {}),
            linkedDependencies,
        };
    }
    return {
        dependenciesTree: ctx.dependenciesTree,
        outdatedDependencies: ctx.outdatedDependencies,
        resolvedImporters,
        resolvedPackagesByPackageId: ctx.resolvedPackagesByPackageId,
        wantedToBeSkippedPackageIds,
    };
}
exports.default = default_1;
function buildTree(ctx, parentNodeId, parentId, children, depth, installable) {
    const childrenNodeIds = {};
    for (const child of children) {
        if (child.pkgId.startsWith('link:')) {
            childrenNodeIds[child.alias] = child.pkgId;
            continue;
        }
        if (nodeIdUtils_1.nodeIdContainsSequence(parentNodeId, parentId, child.pkgId)) {
            continue;
        }
        const childNodeId = nodeIdUtils_1.createNodeId(parentNodeId, child.pkgId);
        childrenNodeIds[child.alias] = childNodeId;
        installable = installable && !ctx.skipped.has(child.pkgId);
        ctx.dependenciesTree[childNodeId] = {
            children: () => buildTree(ctx, childNodeId, child.pkgId, ctx.childrenByParentId[child.pkgId], depth + 1, installable),
            depth,
            installable,
            resolvedPackage: ctx.resolvedPackagesByPackageId[child.pkgId],
        };
    }
    return childrenNodeIds;
}
//# sourceMappingURL=index.js.map