"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.lockfileToPackageRegistry = exports.writePnpFile = exports.lockfileToPnp = void 0;
const config_1 = __importDefault(require("@pnpm/config"));
const lockfile_file_1 = require("@pnpm/lockfile-file");
const lockfile_utils_1 = require("@pnpm/lockfile-utils");
const pkgid_to_filename_1 = __importDefault(require("@pnpm/pkgid-to-filename"));
const read_project_manifest_1 = __importDefault(require("@pnpm/read-project-manifest"));
const dependency_path_1 = require("dependency-path");
const pnp_1 = require("@yarnpkg/pnp");
const fs = require("mz/fs");
const normalizePath = require("normalize-path");
const path = require("path");
const R = require("ramda");
async function lockfileToPnp(lockfileDir) {
    const lockfile = await lockfile_file_1.readWantedLockfile(lockfileDir, { ignoreIncompatible: true });
    if (!lockfile)
        throw new Error('Cannot generate a .pnp.js without a lockfile');
    const importerNames = {};
    await Promise.all(Object.keys(lockfile.importers)
        .map(async (importerId) => {
        const importerDirectory = path.join(lockfileDir, importerId);
        const { manifest } = await read_project_manifest_1.default(importerDirectory);
        importerNames[importerId] = manifest.name;
    }));
    const { config: { registries, virtualStoreDir } } = await config_1.default({
        cliOptions: {},
        packageManager: { name: 'pnpm', version: '*' },
    });
    await writePnpFile(lockfile, {
        importerNames,
        lockfileDir,
        registries,
        virtualStoreDir: virtualStoreDir !== null && virtualStoreDir !== void 0 ? virtualStoreDir : path.join(lockfileDir, 'node_modules/.pnpm'),
    });
}
exports.lockfileToPnp = lockfileToPnp;
async function writePnpFile(lockfile, opts) {
    const packageRegistry = lockfileToPackageRegistry(lockfile, opts);
    const loaderFile = pnp_1.generateInlinedScript({
        blacklistedLocations: undefined,
        dependencyTreeRoots: [],
        ignorePattern: undefined,
        packageRegistry,
        shebang: undefined,
    });
    await fs.writeFile(path.join(opts.lockfileDir, '.pnp.js'), loaderFile, 'utf8');
}
exports.writePnpFile = writePnpFile;
function lockfileToPackageRegistry(lockfile, opts) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j;
    const packageRegistry = new Map();
    for (const importerId of Object.keys(lockfile.importers)) {
        const importer = lockfile.importers[importerId];
        if (importerId === '.') {
            const packageStore = new Map([
                [
                    null,
                    {
                        packageDependencies: new Map([
                            ...((_a = (importer.dependencies && toPackageDependenciesMap(lockfile, importer.dependencies))) !== null && _a !== void 0 ? _a : []),
                            ...((_b = (importer.optionalDependencies && toPackageDependenciesMap(lockfile, importer.optionalDependencies))) !== null && _b !== void 0 ? _b : []),
                            ...((_c = (importer.devDependencies && toPackageDependenciesMap(lockfile, importer.devDependencies))) !== null && _c !== void 0 ? _c : []),
                        ]),
                        packageLocation: './',
                    },
                ],
            ]);
            packageRegistry.set(null, packageStore);
        }
        else {
            const name = opts.importerNames[importerId];
            const packageStore = new Map([
                [
                    importerId,
                    {
                        packageDependencies: new Map([
                            [name, importerId],
                            ...((_d = (importer.dependencies && toPackageDependenciesMap(lockfile, importer.dependencies, importerId))) !== null && _d !== void 0 ? _d : []),
                            ...((_e = (importer.optionalDependencies && toPackageDependenciesMap(lockfile, importer.optionalDependencies, importerId))) !== null && _e !== void 0 ? _e : []),
                            ...((_f = (importer.devDependencies && toPackageDependenciesMap(lockfile, importer.devDependencies, importerId))) !== null && _f !== void 0 ? _f : []),
                        ]),
                        packageLocation: `./${importerId}`,
                    },
                ],
            ]);
            packageRegistry.set(name, packageStore);
        }
    }
    for (const [relDepPath, pkgSnapshot] of R.toPairs((_g = lockfile.packages) !== null && _g !== void 0 ? _g : {})) {
        const { name, version, peersSuffix } = lockfile_utils_1.nameVerFromPkgSnapshot(relDepPath, pkgSnapshot);
        const pnpVersion = toPnPVersion(version, peersSuffix);
        let packageStore = packageRegistry.get(name);
        if (!packageStore) {
            packageStore = new Map();
            packageRegistry.set(name, packageStore);
        }
        // Seems like this field should always contain a relative path
        let packageLocation = normalizePath(path.relative(opts.lockfileDir, path.join(opts.virtualStoreDir, pkgid_to_filename_1.default(relDepPath, opts.lockfileDir), 'node_modules', name)));
        if (!packageLocation.startsWith('../')) {
            packageLocation = `./${packageLocation}`;
        }
        packageStore.set(pnpVersion, {
            packageDependencies: new Map([
                [name, pnpVersion],
                ...((_h = (pkgSnapshot.dependencies && toPackageDependenciesMap(lockfile, pkgSnapshot.dependencies))) !== null && _h !== void 0 ? _h : []),
                ...((_j = (pkgSnapshot.optionalDependencies && toPackageDependenciesMap(lockfile, pkgSnapshot.optionalDependencies))) !== null && _j !== void 0 ? _j : []),
            ]),
            packageLocation,
        });
    }
    return packageRegistry;
}
exports.lockfileToPackageRegistry = lockfileToPackageRegistry;
function toPackageDependenciesMap(lockfile, deps, importerId) {
    return R.toPairs(deps).map(([depAlias, ref]) => {
        if (importerId && ref.startsWith('link:')) {
            return [depAlias, path.join(importerId, ref.substr(5))];
        }
        const relDepPath = dependency_path_1.refToRelative(ref, depAlias);
        if (!relDepPath)
            return [depAlias, ref];
        const { name, version, peersSuffix } = lockfile_utils_1.nameVerFromPkgSnapshot(relDepPath, lockfile.packages[relDepPath]);
        const pnpVersion = toPnPVersion(version, peersSuffix);
        if (depAlias === name) {
            return [depAlias, pnpVersion];
        }
        return [depAlias, [name, pnpVersion]];
    });
}
function toPnPVersion(version, peersSuffix) {
    return peersSuffix
        ? `virtual:${version}_${peersSuffix}#${version}`
        : version;
}
//# sourceMappingURL=index.js.map