"use strict";
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PnpmShrinkwrapFile = exports.ShrinkwrapFileMajorVersion = void 0;
exports.parsePnpm9DependencyKey = parsePnpm9DependencyKey;
exports.parsePnpmDependencyKey = parsePnpmDependencyKey;
exports.normalizePnpmVersionSpecifier = normalizePnpmVersionSpecifier;
const path = __importStar(require("node:path"));
const node_crypto_1 = __importDefault(require("node:crypto"));
const semver = __importStar(require("semver"));
const node_core_library_1 = require("@rushstack/node-core-library");
const terminal_1 = require("@rushstack/terminal");
const BaseShrinkwrapFile_1 = require("../base/BaseShrinkwrapFile");
const DependencySpecifier_1 = require("../DependencySpecifier");
const PnpmYamlCommon_1 = require("./PnpmYamlCommon");
const RushConstants_1 = require("../RushConstants");
const PackageJsonEditor_1 = require("../../api/PackageJsonEditor");
const PnpmfileConfiguration_1 = require("./PnpmfileConfiguration");
const PnpmProjectShrinkwrapFile_1 = require("./PnpmProjectShrinkwrapFile");
const PnpmOptionsConfiguration_1 = require("./PnpmOptionsConfiguration");
const CustomTipsConfiguration_1 = require("../../api/CustomTipsConfiguration");
const PnpmShrinkWrapFileConverters_1 = require("./PnpmShrinkWrapFileConverters");
const yamlModule = node_core_library_1.Import.lazy('js-yaml', require);
const pnpmKitV8 = node_core_library_1.Import.lazy('@rushstack/rush-pnpm-kit-v8', require);
const pnpmKitV9 = node_core_library_1.Import.lazy('@rushstack/rush-pnpm-kit-v9', require);
var ShrinkwrapFileMajorVersion;
(function (ShrinkwrapFileMajorVersion) {
    ShrinkwrapFileMajorVersion[ShrinkwrapFileMajorVersion["V6"] = 6] = "V6";
    ShrinkwrapFileMajorVersion[ShrinkwrapFileMajorVersion["V9"] = 9] = "V9";
})(ShrinkwrapFileMajorVersion || (exports.ShrinkwrapFileMajorVersion = ShrinkwrapFileMajorVersion = {}));
function parsePnpm9DependencyKey(dependencyName, versionSpecifier) {
    var _a, _b, _c;
    if (!versionSpecifier) {
        return undefined;
    }
    const dependencyKey = normalizePnpmVersionSpecifier(versionSpecifier);
    // Example: file:projects/project2
    // Example: project-2@file:projects/project2
    // Example: link:../projects/project1
    if (/(file|link):/.test(dependencyKey)) {
        // If it starts with an NPM scheme such as "file:projects/my-app.tgz", we don't support that
        return undefined;
    }
    const { peersIndex } = pnpmKitV9.dependencyPath.indexOfPeersSuffix(dependencyKey);
    if (peersIndex !== -1) {
        // Remove peer suffix
        const key = dependencyKey.slice(0, peersIndex);
        // Example: 7.26.0
        if (semver.valid(key)) {
            return DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, key);
        }
    }
    // Example: @babel/preset-env@7.26.0                                                          -> name=@babel/preset-env version=7.26.0
    // Example: @babel/preset-env@7.26.0(peer@1.2.3)                                              -> name=@babel/preset-env version=7.26.0
    // Example: https://github.com/jonschlinkert/pad-left/tarball/2.1.0                           -> name=undefined         version=undefined
    // Example: pad-left@https://github.com/jonschlinkert/pad-left/tarball/2.1.0                  -> name=pad-left          nonSemverVersion=https://xxxx
    // Example: pad-left@https://codeload.github.com/jonschlinkert/pad-left/tar.gz/7798d648225aa5 -> name=pad-left          nonSemverVersion=https://xxxx
    const dependency = pnpmKitV9.dependencyPath.parse(dependencyKey);
    const name = (_a = dependency.name) !== null && _a !== void 0 ? _a : dependencyName;
    const version = (_c = (_b = dependency.version) !== null && _b !== void 0 ? _b : dependency.nonSemverVersion) !== null && _c !== void 0 ? _c : dependencyKey;
    // Example: https://xxxx/pad-left/tarball/2.1.0
    // Example: https://github.com/jonschlinkert/pad-left/tarball/2.1.0
    // Example: https://codeload.github.com/jonschlinkert/pad-left/tar.gz/7798d648225aa5d879660a37c408ab4675b65ac7
    if (/^https?:/.test(version)) {
        return DependencySpecifier_1.DependencySpecifier.parseWithCache(name, version);
    }
    // Is it an alias for a different package?
    if (name === dependencyName) {
        // No, it's a regular dependency
        return DependencySpecifier_1.DependencySpecifier.parseWithCache(name, version);
    }
    else {
        // If the parsed package name is different from the dependencyName, then this is an NPM package alias
        return DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, `npm:${name}@${version}`);
    }
}
/**
 * Given an encoded "dependency key" from the PNPM shrinkwrap file, this parses it into an equivalent
 * DependencySpecifier.
 *
 * @returns a SemVer string, or undefined if the version specifier cannot be parsed
 */
function parsePnpmDependencyKey(dependencyName, versionSpecifier) {
    if (!versionSpecifier) {
        return undefined;
    }
    const dependencyKey = normalizePnpmVersionSpecifier(versionSpecifier);
    if (/^\w+:/.test(dependencyKey)) {
        // If it starts with an NPM scheme such as "file:projects/my-app.tgz", we don't support that
        return undefined;
    }
    // The package name parsed from the dependency key, or dependencyName if it was omitted.
    // Example: "@scope/depame"
    let parsedPackageName;
    // The trailing portion of the dependency key that includes the version and optional peer dependency path.
    // Example: "2.8.0/chai@3.5.0+sinon@1.17.7"
    let parsedInstallPath;
    // Example: "path.pkgs.visualstudio.com/@scope/depame/1.4.0"  --> 0="@scope/depame" 1="1.4.0"
    // Example: "/isarray/2.0.1"                                  --> 0="isarray"       1="2.0.1"
    // Example: "/sinon-chai/2.8.0/chai@3.5.0+sinon@1.17.7"       --> 0="sinon-chai"    1="2.8.0/chai@3.5.0+sinon@1.17.7"
    // Example: "/typescript@5.1.6"                               --> 0=typescript      1="5.1.6"
    // Example: 1.2.3_peer-dependency@.4.5.6                      --> no match
    // Example: 1.2.3_@scope+peer-dependency@.4.5.6               --> no match
    // Example: 1.2.3(peer-dependency@.4.5.6)                     --> no match
    // Example: 1.2.3(@scope/peer-dependency@.4.5.6)              --> no match
    const packageNameMatch = /^[^\/(]*\/((?:@[^\/(]+\/)?[^\/(]+)[\/@](.*)$/.exec(dependencyKey);
    if (packageNameMatch) {
        parsedPackageName = packageNameMatch[1];
        parsedInstallPath = packageNameMatch[2];
    }
    else {
        parsedPackageName = dependencyName;
        // Example: "23.6.0_babel-core@6.26.3"
        // Example: "23.6.0"
        parsedInstallPath = dependencyKey;
    }
    // The SemVer value
    // Example: "2.8.0"
    let parsedVersionPart;
    // Example: "23.6.0_babel-core@6.26.3" --> "23.6.0"
    // Example: "2.8.0/chai@3.5.0+sinon@1.17.7" --> "2.8.0"
    // Example: "0.53.1(@types/node@14.18.36)" --> "0.53.1"
    const versionMatch = /^([^\(\/_]+)[(\/_]/.exec(parsedInstallPath);
    if (versionMatch) {
        parsedVersionPart = versionMatch[1];
    }
    else {
        // Example: "2.8.0"
        parsedVersionPart = parsedInstallPath;
    }
    // By this point, we expect parsedVersionPart to be a valid SemVer range
    if (!parsedVersionPart) {
        return undefined;
    }
    if (!semver.valid(parsedVersionPart)) {
        const urlRegex = /^(git@|@)?([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}(\/|\+)([^\/\\]+\/?)*([^\/\\]+)$/i;
        // Test for urls:
        // Examples:
        //     @github.com/abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     github.com/abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     github.com.au/abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     bitbucket.com/abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     bitbucket.com+abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     git@bitbucket.com+abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        //     bitbucket.co.in/abc/def/188ed64efd5218beda276e02f2277bf3a6b745b2
        if (urlRegex.test(dependencyKey)) {
            const dependencySpecifier = DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, dependencyKey);
            return dependencySpecifier;
        }
        else {
            return undefined;
        }
    }
    // Is it an alias for a different package?
    if (parsedPackageName === dependencyName) {
        // No, it's a regular dependency
        return DependencySpecifier_1.DependencySpecifier.parseWithCache(parsedPackageName, parsedVersionPart);
    }
    else {
        // If the parsed package name is different from the dependencyName, then this is an NPM package alias
        return DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, `npm:${parsedPackageName}@${parsedVersionPart}`);
    }
}
function normalizePnpmVersionSpecifier(versionSpecifier) {
    if (typeof versionSpecifier === 'string') {
        return versionSpecifier;
    }
    else {
        return versionSpecifier.version;
    }
}
const cacheByLockfileHash = new Map();
class PnpmShrinkwrapFile extends BaseShrinkwrapFile_1.BaseShrinkwrapFile {
    constructor(shrinkwrapJson, hash, subspaceHasNoProjects) {
        super();
        this.hash = hash;
        this._shrinkwrapJson = shrinkwrapJson;
        cacheByLockfileHash.set(hash, this);
        // Normalize the data
        const lockfileVersion = shrinkwrapJson.lockfileVersion;
        if (typeof lockfileVersion === 'string') {
            const isDotIncluded = lockfileVersion.includes('.');
            this.shrinkwrapFileMajorVersion = parseInt(lockfileVersion.substring(0, isDotIncluded ? lockfileVersion.indexOf('.') : undefined), 10);
        }
        else if (typeof lockfileVersion === 'number') {
            this.shrinkwrapFileMajorVersion = Math.floor(lockfileVersion);
        }
        else {
            this.shrinkwrapFileMajorVersion = 0;
        }
        this.registry = shrinkwrapJson.registry || '';
        this.dependencies = new Map(Object.entries(shrinkwrapJson.dependencies || {}));
        this.importers = new Map(Object.entries(shrinkwrapJson.importers || {}));
        this.specifiers = new Map(Object.entries(shrinkwrapJson.specifiers || {}));
        this.packages = new Map(Object.entries(shrinkwrapJson.packages || {}));
        this.overrides = new Map(Object.entries(shrinkwrapJson.overrides || {}));
        this.packageExtensionsChecksum = shrinkwrapJson.packageExtensionsChecksum;
        let isWorkspaceCompatible;
        const importerCount = this.importers.size;
        if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) {
            // Lockfile v9 always has "." in importers filed.
            if (subspaceHasNoProjects) {
                // If there are no projects in this subspace, the "." importer will be the only importer
                isWorkspaceCompatible = importerCount === 1;
            }
            else {
                isWorkspaceCompatible = importerCount > 1;
            }
        }
        else {
            isWorkspaceCompatible = importerCount > 0;
        }
        this.isWorkspaceCompatible = isWorkspaceCompatible;
        this._integrities = new Map();
    }
    static getLockfileV9PackageId(name, version) {
        /**
         * name@1.2.3                -> name@1.2.3
         * name@1.2.3(peer)          -> name@1.2.3(peer)
         * https://xxx/@a/b          -> name@https://xxx/@a/b
         * file://xxx                -> name@file://xxx
         * 1.2.3                     -> name@1.2.3
         */
        if (/https?:/.test(version)) {
            return /@https?:/.test(version) ? version : `${name}@${version}`;
        }
        else if (/file:/.test(version)) {
            return /@file:/.test(version) ? version : `${name}@${version}`;
        }
        return pnpmKitV9.dependencyPath.removeSuffix(version).includes('@', 1) ? version : `${name}@${version}`;
    }
    /**
     * Clears the cache of PnpmShrinkwrapFile instances to free up memory.
     */
    static clearCache() {
        cacheByLockfileHash.clear();
    }
    static loadFromFile(shrinkwrapYamlFilePath, options) {
        try {
            const shrinkwrapContent = node_core_library_1.FileSystem.readFile(shrinkwrapYamlFilePath);
            return PnpmShrinkwrapFile.loadFromString(shrinkwrapContent, options);
        }
        catch (error) {
            if (node_core_library_1.FileSystem.isNotExistError(error)) {
                return undefined; // file does not exist
            }
            throw new Error(`Error reading "${shrinkwrapYamlFilePath}":\n  ${error.message}`);
        }
    }
    static loadFromString(shrinkwrapContent, options) {
        var _a;
        const hash = node_crypto_1.default.createHash('sha-256').update(shrinkwrapContent, 'utf8').digest('hex');
        const cached = cacheByLockfileHash.get(hash);
        if (cached) {
            return cached;
        }
        const { subspaceHasNoProjects } = options;
        const shrinkwrapJson = yamlModule.load(shrinkwrapContent);
        if (shrinkwrapJson.snapshots) {
            const lockfile = (0, PnpmShrinkWrapFileConverters_1.convertLockfileV9ToLockfileObject)(shrinkwrapJson);
            /**
             * In Lockfile V9,
             * 1. There is no top-level dependencies field, but it is a property of the importers field.
             * 2. The version may is not equal to the key in the package field. Thus, it needs to be standardized in the form of `<name>:<version>`.
             *
             * importers:
             *  .:
             *    dependencies:
             *      'project1':
             *        specifier: file:./projects/project1
             *        version: file:projects/project1
             *
             * packages:
             *   project1@file:projects/project1:
             *     resolution: {directory: projects/project1, type: directory}
             */
            const dependencies = (_a = lockfile.importers['.']) === null || _a === void 0 ? void 0 : _a.dependencies;
            if (dependencies) {
                lockfile.dependencies = {};
                for (const [name, versionSpecifier] of Object.entries(dependencies)) {
                    lockfile.dependencies[name] = PnpmShrinkwrapFile.getLockfileV9PackageId(name, versionSpecifier);
                }
            }
            return new PnpmShrinkwrapFile(lockfile, hash, subspaceHasNoProjects);
        }
        return new PnpmShrinkwrapFile(shrinkwrapJson, hash, subspaceHasNoProjects);
    }
    getShrinkwrapHash(experimentsConfig) {
        // The 'omitImportersFromPreventManualShrinkwrapChanges' experiment skips the 'importers' section
        // when computing the hash, since the main concern is changes to the overall external dependency footprint
        const { omitImportersFromPreventManualShrinkwrapChanges } = experimentsConfig || {};
        const shrinkwrapContent = this._serializeInternal(omitImportersFromPreventManualShrinkwrapChanges);
        return node_crypto_1.default.createHash('sha1').update(shrinkwrapContent).digest('hex');
    }
    /**
     * Determine whether `pnpm-lock.yaml` contains insecure sha1 hashes.
     * @internal
     */
    _disallowInsecureSha1(customTipsConfiguration, exemptPackageVersions, terminal, subspaceName) {
        var _a;
        const exemptPackageList = new Map();
        for (const [pkgName, versions] of Object.entries(exemptPackageVersions)) {
            for (const version of versions) {
                exemptPackageList.set(this._getPackageId(pkgName, version), true);
            }
        }
        for (const [pkgName, { resolution }] of this.packages) {
            if (((_a = resolution === null || resolution === void 0 ? void 0 : resolution.integrity) === null || _a === void 0 ? void 0 : _a.startsWith('sha1')) &&
                !exemptPackageList.has(this._parseDependencyPath(pkgName))) {
                terminal.writeErrorLine('Error: An integrity field with "sha1" was detected in the pnpm-lock.yaml file located in subspace ' +
                    `${subspaceName}; this conflicts with the "disallowInsecureSha1" policy from pnpm-config.json.\n`);
                customTipsConfiguration._showErrorTip(terminal, CustomTipsConfiguration_1.CustomTipId.TIP_RUSH_DISALLOW_INSECURE_SHA1);
                return true; // Indicates an error was found
            }
        }
        return false;
    }
    /** @override */
    validateShrinkwrapAfterUpdate(rushConfiguration, subspace, terminal) {
        var _a;
        const pnpmOptions = subspace.getPnpmOptions() || rushConfiguration.pnpmOptions;
        const { pnpmLockfilePolicies } = pnpmOptions;
        let invalidPoliciesCount = 0;
        if ((_a = pnpmLockfilePolicies === null || pnpmLockfilePolicies === void 0 ? void 0 : pnpmLockfilePolicies.disallowInsecureSha1) === null || _a === void 0 ? void 0 : _a.enabled) {
            const isError = this._disallowInsecureSha1(rushConfiguration.customTipsConfiguration, pnpmLockfilePolicies.disallowInsecureSha1.exemptPackageVersions, terminal, subspace.subspaceName);
            if (isError) {
                invalidPoliciesCount += 1;
            }
        }
        if (invalidPoliciesCount > 0) {
            throw new node_core_library_1.AlreadyReportedError();
        }
    }
    /** @override */
    validate(packageManagerOptionsConfig, policyOptions, experimentsConfig) {
        super.validate(packageManagerOptionsConfig, policyOptions);
        if (!(packageManagerOptionsConfig instanceof PnpmOptionsConfiguration_1.PnpmOptionsConfiguration)) {
            throw new Error('The provided package manager options are not valid for PNPM shrinkwrap files.');
        }
        if (!policyOptions.allowShrinkwrapUpdates) {
            if (!policyOptions.repoState.isValid) {
                // eslint-disable-next-line no-console
                console.log(terminal_1.Colorize.red(`The ${RushConstants_1.RushConstants.repoStateFilename} file is invalid. There may be a merge conflict marker ` +
                    'in the file. You may need to run "rush update" to refresh its contents.') + '\n');
                throw new node_core_library_1.AlreadyReportedError();
            }
            // Only check the hash if allowShrinkwrapUpdates is false. If true, the shrinkwrap file
            // may have changed and the hash could be invalid.
            if (packageManagerOptionsConfig.preventManualShrinkwrapChanges) {
                if (!policyOptions.repoState.pnpmShrinkwrapHash) {
                    // eslint-disable-next-line no-console
                    console.log(terminal_1.Colorize.red('The existing shrinkwrap file hash could not be found. You may need to run "rush update" to ' +
                        'populate the hash. See the "preventManualShrinkwrapChanges" setting documentation for details.') + '\n');
                    throw new node_core_library_1.AlreadyReportedError();
                }
                if (this.getShrinkwrapHash(experimentsConfig) !== policyOptions.repoState.pnpmShrinkwrapHash) {
                    // eslint-disable-next-line no-console
                    console.log(terminal_1.Colorize.red('The shrinkwrap file hash does not match the expected hash. Please run "rush update" to ensure the ' +
                        'shrinkwrap file is up to date. See the "preventManualShrinkwrapChanges" setting documentation for ' +
                        'details.') + '\n');
                    throw new node_core_library_1.AlreadyReportedError();
                }
            }
        }
    }
    /**
     * This operation exactly mirrors the behavior of PNPM's own implementation:
     * https://github.com/pnpm/pnpm/blob/73ebfc94e06d783449579cda0c30a40694d210e4/lockfile/lockfile-file/src/experiments/inlineSpecifiersLockfileConverters.ts#L162
     */
    _convertLockfileV6DepPathToV5DepPath(newDepPath) {
        if (!newDepPath.includes('@', 2) || newDepPath.startsWith('file:'))
            return newDepPath;
        const index = newDepPath.indexOf('@', newDepPath.indexOf('/@') + 2);
        if (newDepPath.includes('(') && index > pnpmKitV8.dependencyPath.indexOfPeersSuffix(newDepPath))
            return newDepPath;
        return `${newDepPath.substring(0, index)}/${newDepPath.substring(index + 1)}`;
    }
    /**
     * Normalize dependency paths for PNPM shrinkwrap files.
     * Example: "/eslint-utils@3.0.0(eslint@8.23.1)" --> "/eslint-utils@3.0.0"
     * Example: "/@typescript-eslint/experimental-utils/5.9.1_eslint@8.6.0+typescript@4.4.4" --> "/@typescript-eslint/experimental-utils/5.9.1"
     */
    _parseDependencyPath(packagePath) {
        let name;
        let version;
        /**
         * For PNPM lockfile version 9 and above, use pnpmKitV9 to parse the dependency path.
         * Example: "@some/pkg@1.0.0" --> "@some/pkg@1.0.0"
         * Example: "@some/pkg@1.0.0(peer@2.0.0)" --> "@some/pkg@1.0.0"
         * Example: "pkg@1.0.0(patch_hash)" --> "pkg@1.0.0"
         */
        if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) {
            ({ name, version } = pnpmKitV9.dependencyPath.parse(packagePath));
        }
        else {
            if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V6) {
                packagePath = this._convertLockfileV6DepPathToV5DepPath(packagePath);
            }
            ({ name, version } = pnpmKitV8.dependencyPath.parse(packagePath));
        }
        if (!name || !version) {
            throw new node_core_library_1.InternalError(`Unable to parse package path: ${packagePath}`);
        }
        return this._getPackageId(name, version);
    }
    /** @override */
    getTempProjectNames() {
        return this._getTempProjectNames(this._shrinkwrapJson.dependencies || {});
    }
    /**
     * Gets the path to the tarball file if the package is a tarball.
     * Returns undefined if the package entry doesn't exist or the package isn't a tarball.
     * Example of return value: file:projects/build-tools.tgz
     */
    getTarballPath(packageName) {
        var _a;
        const dependency = this.packages.get(packageName);
        return (_a = dependency === null || dependency === void 0 ? void 0 : dependency.resolution) === null || _a === void 0 ? void 0 : _a.tarball;
    }
    getTopLevelDependencyKey(dependencyName) {
        return this.dependencies.get(dependencyName);
    }
    /**
     * Gets the version number from the list of top-level dependencies in the "dependencies" section
     * of the shrinkwrap file. Sample return values:
     *   '2.1.113'
     *   '1.9.0-dev.27'
     *   'file:projects/empty-webpart-project.tgz'
     *   undefined
     *
     * @override
     */
    getTopLevelDependencyVersion(dependencyName) {
        var _a, _b;
        let value = this.dependencies.get(dependencyName);
        if (value) {
            value = normalizePnpmVersionSpecifier(value);
            // Getting the top level dependency version from a PNPM lockfile version 5.x or 6.1
            // --------------------------------------------------------------------------
            //
            // 1) Top-level tarball dependency entries in pnpm-lock.yaml look like in 5.x:
            //    ```
            //    '@rush-temp/sp-filepicker': 'file:projects/sp-filepicker.tgz_0ec79d3b08edd81ebf49cd19ca50b3f5'
            //    ```
            //    And in version 6.1, they look like:
            //    ```
            //    '@rush-temp/sp-filepicker':
            //      specifier: file:./projects/generate-api-docs.tgz
            //      version: file:projects/generate-api-docs.tgz
            //    ```
            //    Then, it would be defined below (version 5.x):
            //    ```
            //    'file:projects/sp-filepicker.tgz_0ec79d3b08edd81ebf49cd19ca50b3f5':
            //      dependencies:
            //       '@microsoft/load-themed-styles': 1.10.7
            //       ...
            //      resolution:
            //       integrity: sha512-guuoFIc**==
            //       tarball: 'file:projects/sp-filepicker.tgz'
            //    ```
            //    Or in version 6.1:
            //    ```
            //    file:projects/sp-filepicker.tgz:
            //      resolution: {integrity: sha512-guuoFIc**==, tarball: file:projects/sp-filepicker.tgz}
            //      name: '@rush-temp/sp-filepicker'
            //      version: 0.0.0
            //      dependencies:
            //        '@microsoft/load-themed-styles': 1.10.7
            //        ...
            //      dev: false
            //    ```
            //    Here, we are interested in the part 'file:projects/sp-filepicker.tgz'. Splitting by underscores is not the
            //    best way to get this because file names could have underscores in them. Instead, we could use the tarball
            //    field in the resolution section.
            // 2) Top-level non-tarball dependency entries in pnpm-lock.yaml would look like in 5.x:
            //    ```
            //    '@rushstack/set-webpack-public-path-plugin': 2.1.133
            //    @microsoft/sp-build-node': 1.9.0-dev.27_typescript@2.9.2
            //    ```
            //    And in version 6.1, they look like:
            //    ```
            //    '@rushstack/set-webpack-public-path-plugin':
            //      specifier: ^2.1.133
            //      version: 2.1.133
            //    '@microsoft/sp-build-node':
            //      specifier: 1.9.0-dev.27
            //      version: 1.9.0-dev.27(typescript@2.9.2)
            //    ```
            //    Here, we could either just split by underscores and take the first part (5.x) or use the specifier field
            //    (6.1).
            // The below code is also compatible with lockfile versions < 5.1
            const dependency = this.packages.get(value);
            if (((_a = dependency === null || dependency === void 0 ? void 0 : dependency.resolution) === null || _a === void 0 ? void 0 : _a.tarball) && value.startsWith(dependency.resolution.tarball)) {
                return DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, dependency.resolution.tarball);
            }
            if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) {
                const { version, nonSemverVersion } = pnpmKitV9.dependencyPath.parse(value);
                value = (_b = version !== null && version !== void 0 ? version : nonSemverVersion) !== null && _b !== void 0 ? _b : value;
            }
            else {
                let underscoreOrParenthesisIndex = value.indexOf('_');
                if (underscoreOrParenthesisIndex < 0) {
                    underscoreOrParenthesisIndex = value.indexOf('(');
                }
                if (underscoreOrParenthesisIndex >= 0) {
                    value = value.substring(0, underscoreOrParenthesisIndex);
                }
            }
            return DependencySpecifier_1.DependencySpecifier.parseWithCache(dependencyName, value);
        }
        return undefined;
    }
    /**
     * The PNPM shrinkwrap file has top-level dependencies on the temp projects like this (version 5.x):
     *
     * ```
     * dependencies:
     *   '@rush-temp/my-app': 'file:projects/my-app.tgz_25c559a5921686293a001a397be4dce0'
     * packages:
     *   /@types/node/10.14.15:
     *     dev: false
     *   'file:projects/my-app.tgz_25c559a5921686293a001a397be4dce0':
     *     dev: false
     *     name: '@rush-temp/my-app'
     *     version: 0.0.0
     * ```
     *
     * or in version 6.1, like this:
     * ```
     * dependencies:
     *  '@rush-temp/my-app':
     *    specifier: file:./projects/my-app.tgz
     *    version: file:projects/my-app.tgz
     *  packages:
     *    /@types/node@10.14.15:
     *      resolution: {integrity: sha512-iAB+**==}
     *      dev: false
     *    file:projects/my-app.tgz
     *      resolution: {integrity: sha512-guuoFIc**==, tarball: file:projects/sp-filepicker.tgz}
     *      name: '@rush-temp/my-app'
     *      version: 0.0.0
     *      dependencies:
     *        '@microsoft/load-themed-styles': 1.10.7
     *        ...
     *      dev: false
     * ```
     *
     * We refer to 'file:projects/my-app.tgz_25c559a5921686293a001a397be4dce0' or 'file:projects/my-app.tgz' as
     * the temp project dependency key of the temp project '@rush-temp/my-app'.
     */
    getTempProjectDependencyKey(tempProjectName) {
        const tempProjectDependencyKey = this.dependencies.get(tempProjectName);
        return tempProjectDependencyKey ? normalizePnpmVersionSpecifier(tempProjectDependencyKey) : undefined;
    }
    getShrinkwrapEntryFromTempProjectDependencyKey(tempProjectDependencyKey) {
        return this.packages.get(tempProjectDependencyKey);
    }
    getShrinkwrapEntry(name, version) {
        const packageId = this._getPackageId(name, version);
        return this.packages.get(packageId);
    }
    /**
     * Serializes the PNPM Shrinkwrap file
     *
     * @override
     */
    serialize() {
        return this._serializeInternal(false);
    }
    /**
     * Gets the resolved version number of a dependency for a specific temp project.
     * For PNPM, we can reuse the version that another project is using.
     * Note that this function modifies the shrinkwrap data if tryReusingPackageVersionsFromShrinkwrap is set to true.
     *
     * @override
     */
    tryEnsureDependencyVersion(dependencySpecifier, tempProjectName) {
        // PNPM doesn't have the same advantage of NPM, where we can skip generate as long as the
        // shrinkwrap file puts our dependency in either the top of the node_modules folder
        // or underneath the package we are looking at.
        // This is because the PNPM shrinkwrap file describes the exact links that need to be created
        // to recreate the graph..
        // Because of this, we actually need to check for a version that this package is directly
        // linked to.
        const packageName = dependencySpecifier.packageName;
        const tempProjectDependencyKey = this.getTempProjectDependencyKey(tempProjectName);
        if (!tempProjectDependencyKey) {
            return undefined;
        }
        const packageDescription = this._getPackageDescription(tempProjectDependencyKey);
        if (!packageDescription ||
            !packageDescription.dependencies ||
            !packageDescription.dependencies.hasOwnProperty(packageName)) {
            return undefined;
        }
        const dependencyKey = packageDescription.dependencies[packageName];
        return this._parsePnpmDependencyKey(packageName, dependencyKey);
    }
    /** @override */
    findOrphanedProjects(rushConfiguration, subspace) {
        // The base shrinkwrap handles orphaned projects the same across all package managers,
        // but this is only valid for non-workspace installs
        if (!this.isWorkspaceCompatible) {
            return super.findOrphanedProjects(rushConfiguration, subspace);
        }
        const subspaceTempFolder = subspace.getSubspaceTempFolderPath();
        const lookup = rushConfiguration.getProjectLookupForRoot(subspaceTempFolder);
        const orphanedProjectPaths = [];
        for (const importerKey of this.getImporterKeys()) {
            if (!lookup.findChildPath(importerKey)) {
                // PNPM importer keys are relative paths from the workspace root, which is the common temp folder
                orphanedProjectPaths.push(path.resolve(subspaceTempFolder, importerKey));
            }
        }
        return orphanedProjectPaths;
    }
    /** @override */
    getProjectShrinkwrap(project) {
        return new PnpmProjectShrinkwrapFile_1.PnpmProjectShrinkwrapFile(this, project);
    }
    *getImporterKeys() {
        // Filter out the root importer used for the generated package.json in the root
        // of the install, since we do not use this.
        for (const key of this.importers.keys()) {
            if (key !== '.') {
                yield key;
            }
        }
    }
    getImporterKeyByPath(workspaceRoot, projectFolder) {
        return node_core_library_1.Path.convertToSlashes(path.relative(workspaceRoot, projectFolder));
    }
    getImporter(importerKey) {
        return this.importers.get(importerKey);
    }
    getIntegrityForImporter(importerKey) {
        // This logic formerly lived in PnpmProjectShrinkwrapFile. Moving it here allows caching of the external
        // dependency integrity relationships across projects
        let integrityMap = this._integrities.get(importerKey);
        if (!integrityMap) {
            const importer = this.getImporter(importerKey);
            if (importer) {
                integrityMap = new Map();
                this._integrities.set(importerKey, integrityMap);
                const sha256Digest = node_crypto_1.default
                    .createHash('sha256')
                    .update(JSON.stringify(importer))
                    .digest('base64');
                const selfIntegrity = `${importerKey}:${sha256Digest}:`;
                integrityMap.set(importerKey, selfIntegrity);
                const { dependencies, devDependencies, optionalDependencies } = importer;
                const externalFilter = (name, versionSpecifier) => {
                    const version = normalizePnpmVersionSpecifier(versionSpecifier);
                    return !version.includes('link:');
                };
                if (dependencies) {
                    this._addIntegrities(integrityMap, dependencies, false, externalFilter);
                }
                if (devDependencies) {
                    this._addIntegrities(integrityMap, devDependencies, false, externalFilter);
                }
                if (optionalDependencies) {
                    this._addIntegrities(integrityMap, optionalDependencies, true, externalFilter);
                }
            }
        }
        return integrityMap;
    }
    /** @override */
    async isWorkspaceProjectModifiedAsync(project, subspace, variant) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
        const importerKey = this.getImporterKeyByPath(subspace.getSubspaceTempFolderPath(), project.projectFolder);
        const importer = this.getImporter(importerKey);
        if (!importer) {
            return true;
        }
        // First, let's transform the package.json using the pnpmfile
        const packageJson = project.packageJsonEditor.saveToObject();
        // Initialize the pnpmfile if it doesn't exist
        if (!this._pnpmfileConfiguration) {
            this._pnpmfileConfiguration = await PnpmfileConfiguration_1.PnpmfileConfiguration.initializeAsync(project.rushConfiguration, subspace, variant);
        }
        let transformedPackageJson = packageJson;
        let subspacePnpmfile;
        if (project.rushConfiguration.subspacesFeatureEnabled) {
            // Get the pnpmfile
            const subspacePnpmfilePath = path.join(subspace.getSubspaceTempFolderPath(), RushConstants_1.RushConstants.pnpmfileGlobalFilename);
            if (await node_core_library_1.FileSystem.existsAsync(subspacePnpmfilePath)) {
                try {
                    subspacePnpmfile = require(subspacePnpmfilePath);
                }
                catch (err) {
                    if (err instanceof SyntaxError) {
                        // eslint-disable-next-line no-console
                        console.error(terminal_1.Colorize.red(`A syntax error in the ${RushConstants_1.RushConstants.pnpmfileV6Filename} at ${subspacePnpmfilePath}\n`));
                    }
                    else {
                        // eslint-disable-next-line no-console
                        console.error(terminal_1.Colorize.red(`Error during pnpmfile execution. pnpmfile: "${subspacePnpmfilePath}". Error: "${err.message}".` +
                            '\n'));
                    }
                }
            }
            if (subspacePnpmfile) {
                const individualContext = {
                    log: (message) => {
                        // eslint-disable-next-line no-console
                        console.log(message);
                    }
                };
                try {
                    transformedPackageJson =
                        ((_b = (_a = subspacePnpmfile.hooks) === null || _a === void 0 ? void 0 : _a.readPackage) === null || _b === void 0 ? void 0 : _b.call(_a, transformedPackageJson, individualContext)) ||
                            transformedPackageJson;
                }
                catch (err) {
                    // eslint-disable-next-line no-console
                    console.error(terminal_1.Colorize.red(`Error during readPackage hook execution. pnpmfile: "${subspacePnpmfilePath}". Error: "${err.message}".` +
                        '\n'));
                }
            }
        }
        // Use a new PackageJsonEditor since it will classify each dependency type, making tracking the
        // found versions much simpler.
        const { dependencyList, devDependencyList, dependencyMetaList } = PackageJsonEditor_1.PackageJsonEditor.fromObject(this._pnpmfileConfiguration.transform(transformedPackageJson), project.packageJsonEditor.filePath);
        const allDependencies = [...dependencyList, ...devDependencyList];
        if (this.shrinkwrapFileMajorVersion < ShrinkwrapFileMajorVersion.V6) {
            // PNPM <= v7
            // Then get the unique package names and map them to package versions.
            const dependencyVersions = new Map();
            for (const packageDependency of allDependencies) {
                // We will also filter out peer dependencies since these are not installed at development time.
                if (packageDependency.dependencyType === PackageJsonEditor_1.DependencyType.Peer) {
                    continue;
                }
                const foundDependency = dependencyVersions.get(packageDependency.name);
                if (!foundDependency) {
                    dependencyVersions.set(packageDependency.name, packageDependency);
                }
                else {
                    // Shrinkwrap will prioritize optional dependencies, followed by regular dependencies, with dev being
                    // the least prioritized. We will only keep the most prioritized option.
                    // See: https://github.com/pnpm/pnpm/blob/main/packages/lockfile-utils/src/satisfiesPackageManifest.ts
                    switch (foundDependency.dependencyType) {
                        case PackageJsonEditor_1.DependencyType.Optional:
                            break;
                        case PackageJsonEditor_1.DependencyType.Regular:
                            if (packageDependency.dependencyType === PackageJsonEditor_1.DependencyType.Optional) {
                                dependencyVersions.set(packageDependency.name, packageDependency);
                            }
                            break;
                        case PackageJsonEditor_1.DependencyType.Dev:
                            dependencyVersions.set(packageDependency.name, packageDependency);
                            break;
                    }
                }
            }
            // Then validate that the dependency fields are as expected in the shrinkwrap to avoid false-negatives
            // when moving a package from one field to the other.
            for (const { dependencyType, name } of dependencyVersions.values()) {
                switch (dependencyType) {
                    case PackageJsonEditor_1.DependencyType.Optional:
                        if (!((_c = importer.optionalDependencies) === null || _c === void 0 ? void 0 : _c[name]))
                            return true;
                        break;
                    case PackageJsonEditor_1.DependencyType.Regular:
                        if (!((_d = importer.dependencies) === null || _d === void 0 ? void 0 : _d[name]))
                            return true;
                        break;
                    case PackageJsonEditor_1.DependencyType.Dev:
                        if (!((_e = importer.devDependencies) === null || _e === void 0 ? void 0 : _e[name]))
                            return true;
                        break;
                }
            }
            const specifiers = importer.specifiers;
            if (!specifiers) {
                throw new node_core_library_1.InternalError('Expected specifiers to be defined, but is expected in lockfile version 5');
            }
            // Then validate the length matches between the importer and the dependency list, since duplicates are
            // a valid use-case. Importers will only take one of these values, so no need to do more work here.
            if (dependencyVersions.size !== Object.keys(specifiers).length) {
                return true;
            }
            // Finally, validate that all values in the importer are also present in the dependency list.
            for (const [importerPackageName, importerVersionSpecifier] of Object.entries(specifiers)) {
                const foundDependency = dependencyVersions.get(importerPackageName);
                if (!foundDependency) {
                    return true;
                }
                const resolvedVersion = (_f = this.overrides.get(importerPackageName)) !== null && _f !== void 0 ? _f : foundDependency.version;
                if (resolvedVersion !== importerVersionSpecifier) {
                    return true;
                }
            }
        }
        else {
            //  >= PNPM v8
            const importerOptionalDependencies = new Set(Object.keys((_g = importer.optionalDependencies) !== null && _g !== void 0 ? _g : {}));
            const importerDependencies = new Set(Object.keys((_h = importer.dependencies) !== null && _h !== void 0 ? _h : {}));
            const importerDevDependencies = new Set(Object.keys((_j = importer.devDependencies) !== null && _j !== void 0 ? _j : {}));
            const importerDependenciesMeta = new Set(Object.keys((_k = importer.dependenciesMeta) !== null && _k !== void 0 ? _k : {}));
            for (const { dependencyType, name, version } of allDependencies) {
                let isOptional = false;
                let specifierFromLockfile;
                let isDevDepFallThrough = false;
                switch (dependencyType) {
                    case PackageJsonEditor_1.DependencyType.Optional: {
                        specifierFromLockfile = (_l = importer.optionalDependencies) === null || _l === void 0 ? void 0 : _l[name];
                        importerOptionalDependencies.delete(name);
                        break;
                    }
                    case PackageJsonEditor_1.DependencyType.Peer: {
                        // Peer dependencies of workspace projects may be installed as regular dependencies
                        isOptional = true; // fall through
                    }
                    case PackageJsonEditor_1.DependencyType.Dev: {
                        specifierFromLockfile = (_m = importer.devDependencies) === null || _m === void 0 ? void 0 : _m[name];
                        if (specifierFromLockfile) {
                            // If the dev dependency is not found, it may be installed as a regular dependency,
                            // so fall through
                            importerDevDependencies.delete(name);
                            break;
                        }
                        // If fall through, there is a chance the package declares an inconsistent version, ignore it.
                        isDevDepFallThrough = true;
                    }
                    // eslint-disable-next-line no-fallthrough
                    case PackageJsonEditor_1.DependencyType.Regular:
                        specifierFromLockfile = (_o = importer.dependencies) === null || _o === void 0 ? void 0 : _o[name];
                        importerDependencies.delete(name);
                        break;
                }
                if (!specifierFromLockfile) {
                    if (!isOptional) {
                        return true;
                    }
                }
                else {
                    if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) {
                        // TODO: Emit an error message when someone tries to override a version of something in one of their
                        // local repo packages.
                        let resolvedVersion = (_p = this.overrides.get(name)) !== null && _p !== void 0 ? _p : version;
                        // convert path in posix style, otherwise pnpm install will fail in subspace case
                        resolvedVersion = node_core_library_1.Path.convertToSlashes(resolvedVersion);
                        const specifier = importer.specifiers[name];
                        if (specifier !== resolvedVersion && !isDevDepFallThrough && !isOptional) {
                            return true;
                        }
                    }
                    else {
                        if (typeof specifierFromLockfile === 'string') {
                            throw new Error(`The PNPM lockfile is in an unexpected format. The "${name}" package is specified as ` +
                                `"${specifierFromLockfile}" instead of an object.`);
                        }
                        else {
                            // TODO: Emit an error message when someone tries to override a version of something in one of their
                            // local repo packages.
                            let resolvedVersion = (_q = this.overrides.get(name)) !== null && _q !== void 0 ? _q : version;
                            // convert path in posix style, otherwise pnpm install will fail in subspace case
                            resolvedVersion = node_core_library_1.Path.convertToSlashes(resolvedVersion);
                            if (specifierFromLockfile.specifier !== resolvedVersion &&
                                !isDevDepFallThrough &&
                                !isOptional) {
                                return true;
                            }
                        }
                    }
                }
            }
            for (const { name, injected } of dependencyMetaList) {
                if (((_s = (_r = importer.dependenciesMeta) === null || _r === void 0 ? void 0 : _r[name]) === null || _s === void 0 ? void 0 : _s.injected) === injected) {
                    importerDependenciesMeta.delete(name);
                }
            }
            // Finally, validate that all values in the importer are also present in the dependency list.
            if (importerOptionalDependencies.size > 0 ||
                importerDependencies.size > 0 ||
                importerDevDependencies.size > 0 ||
                importerDependenciesMeta.size > 0) {
                return true;
            }
        }
        return false;
    }
    _getIntegrityForPackage(specifier, optional) {
        const integrities = this._integrities;
        let integrityMap = integrities.get(specifier);
        if (integrityMap) {
            return integrityMap;
        }
        integrityMap = new Map();
        integrities.set(specifier, integrityMap);
        const shrinkwrapEntry = this.packages.get(specifier);
        if (!shrinkwrapEntry) {
            if (!optional) {
                // This algorithm heeds to be robust against missing shrinkwrap entries, so we can't just throw
                // Instead set it to a value which will not match any valid shrinkwrap record
                integrityMap.set(specifier, 'Missing shrinkwrap entry!');
            }
            // Indicate an empty entry
            return integrityMap;
        }
        // Hash the full shrinkwrap entry instead of using just resolution.integrity.
        // This ensures that changes to sub-dependency resolutions are detected.
        // For example, if package A depends on B@1.0 and B@1.0's resolution of C changes
        // from C@1.3 to C@1.2, the hash of A's shrinkwrap entry will change because
        // the dependencies field in the entry reflects the resolved versions.
        const sha256Digest = node_crypto_1.default
            .createHash('sha256')
            .update(JSON.stringify(shrinkwrapEntry))
            .digest('base64');
        const selfIntegrity = `${specifier}:${sha256Digest}:`;
        integrityMap.set(specifier, selfIntegrity);
        const { dependencies, optionalDependencies } = shrinkwrapEntry;
        if (dependencies) {
            this._addIntegrities(integrityMap, dependencies, false);
        }
        if (optionalDependencies) {
            this._addIntegrities(integrityMap, optionalDependencies, true);
        }
        return integrityMap;
    }
    _addIntegrities(integrityMap, collection, optional, filter) {
        for (const [name, version] of Object.entries(collection)) {
            if (filter && !filter(name, version)) {
                continue;
            }
            const packageId = this._getPackageId(name, version);
            if (integrityMap.has(packageId)) {
                // The entry could already have been added as a nested dependency
                continue;
            }
            const contribution = this._getIntegrityForPackage(packageId, optional);
            for (const [dep, integrity] of contribution) {
                integrityMap.set(dep, integrity);
            }
        }
    }
    /**
     * Gets the package description for a tempProject from the shrinkwrap file.
     */
    _getPackageDescription(tempProjectDependencyKey) {
        const packageDescription = this.packages.get(tempProjectDependencyKey);
        return packageDescription && packageDescription.dependencies ? packageDescription : undefined;
    }
    _getPackageId(name, versionSpecifier) {
        const version = normalizePnpmVersionSpecifier(versionSpecifier);
        if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9) {
            return PnpmShrinkwrapFile.getLockfileV9PackageId(name, version);
        }
        else if (this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V6) {
            if (version.startsWith('@github')) {
                // This is a github repo reference
                return version;
            }
            else {
                return version.startsWith('/') ? version : `/${name}@${version}`;
            }
        }
        else {
            // Version can sometimes be in the form of a path that's already in the /name/version format.
            return version.indexOf('/') !== -1 ? version : `/${name}/${version}`;
        }
    }
    _parsePnpmDependencyKey(dependencyName, pnpmDependencyKey) {
        if (pnpmDependencyKey) {
            const result = this.shrinkwrapFileMajorVersion >= ShrinkwrapFileMajorVersion.V9
                ? parsePnpm9DependencyKey(dependencyName, pnpmDependencyKey)
                : parsePnpmDependencyKey(dependencyName, pnpmDependencyKey);
            if (!result) {
                throw new Error(`Cannot parse PNPM shrinkwrap version specifier: "${pnpmDependencyKey}"` +
                    ` for "${dependencyName}"`);
            }
            return result;
        }
        else {
            return undefined;
        }
    }
    _serializeInternal(omitImporters = false) {
        // Ensure that if any of the top-level properties are provided but empty are removed. We populate the object
        // properties when we read the shrinkwrap but PNPM does not set these top-level properties unless they are present.
        const shrinkwrapToSerialize = {};
        for (const [key, value] of Object.entries(this._shrinkwrapJson)) {
            if (omitImporters && key === 'importers') {
                continue;
            }
            if (!value || typeof value !== 'object' || Object.keys(value).length > 0) {
                shrinkwrapToSerialize[key] = value;
            }
        }
        return yamlModule.dump(shrinkwrapToSerialize, PnpmYamlCommon_1.PNPM_SHRINKWRAP_YAML_FORMAT);
    }
}
exports.PnpmShrinkwrapFile = PnpmShrinkwrapFile;
//# sourceMappingURL=PnpmShrinkwrapFile.js.map