"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const promises_1 = __importDefault(require("fs/promises"));
const globby_1 = __importDefault(require("globby"));
const js_yaml_1 = __importDefault(require("js-yaml"));
const path_1 = __importDefault(require("path"));
const untildify_1 = __importDefault(require("untildify"));
const findPackage_1 = __importDefault(require("./findPackage"));
const loadPackageInfoFromFile_1 = __importDefault(require("./loadPackageInfoFromFile"));
const programError_1 = __importDefault(require("./programError"));
/** Reads, parses, and resolves workspaces from a pnpm-workspace file at the same path as the package file. */
const readPnpmWorkspaces = async (pkgPath) => {
    const pnpmWorkspacesPath = path_1.default.join(path_1.default.dirname(pkgPath), 'pnpm-workspace.yaml');
    let pnpmWorkspaceFile;
    try {
        pnpmWorkspaceFile = await promises_1.default.readFile(pnpmWorkspacesPath, 'utf-8');
    }
    catch (e) {
        return null;
    }
    return js_yaml_1.default.load(pnpmWorkspaceFile);
};
/**
 * Gets all workspace packages information.
 *
 * @param options the application options, used to determine which packages to return.
 * @param defaultPackageFilename the default package filename
 * @returns a list of PackageInfo objects, one for each workspace file
 */
async function getWorkspacePackageInfos(options, defaultPackageFilename, rootPackageFile, cwd) {
    // use silent, otherwise there will be a duplicate "Checking" message
    const { pkgData, pkgPath } = await (0, findPackage_1.default)({ ...options, packageFile: rootPackageFile, loglevel: 'silent' });
    const rootPkg = typeof pkgData === 'string' ? JSON.parse(pkgData) : pkgData;
    const workspacesObject = rootPkg.workspaces || (await readPnpmWorkspaces(pkgPath || ''));
    const workspaces = Array.isArray(workspacesObject) ? workspacesObject : workspacesObject === null || workspacesObject === void 0 ? void 0 : workspacesObject.packages;
    if (!workspaces) {
        (0, programError_1.default)(options, `workspaces property missing from package.json. --workspace${options.workspaces ? 's' : ''} only works when you specify a "workspaces" property in your package.json.`);
    }
    // build a glob from the workspaces
    // FIXME: the following workspaces check is redundant
    /* c8 ignore next */
    const workspacePackageGlob = (workspaces || []).map(workspace => path_1.default
        .join(cwd, workspace, 'package.json')
        // convert Windows path to *nix path for globby
        .replace(/\\/g, '/'));
    // e.g. [packages/a/package.json, ...]
    const allWorkspacePackageFilepaths = [
        ...globby_1.default.sync(workspacePackageGlob, {
            ignore: ['**/node_modules/**'],
        }),
    ];
    // Get the package names from the package files.
    // If a package does not have a name, use the folder name.
    // These will be used to filter out local workspace packages so they are not fetched from the registry.
    const allWorkspacePackageInfos = [
        ...(await Promise.all(allWorkspacePackageFilepaths.map(async (filepath) => {
            const info = await (0, loadPackageInfoFromFile_1.default)(options, filepath);
            info.name = info.pkg.name || filepath.split('/').slice(-2)[0];
            return info;
        }))),
    ];
    // Workspace package names
    // These will be used to filter out local workspace packages so they are not fetched from the registry.
    const allWorkspacePackageNames = allWorkspacePackageInfos.map((packageInfo) => packageInfo.name || '');
    const filterWorkspaces = options.workspaces !== true;
    if (!filterWorkspaces) {
        // --workspaces
        return [allWorkspacePackageInfos, allWorkspacePackageNames];
    }
    // add workspace packages
    // --workspace
    const selectedWorkspacePackageInfos = allWorkspacePackageInfos.filter((packageInfo) => {
        var _a;
        /* ignore coverage on optional-chaining */
        /* c8 ignore next */
        return (_a = options.workspace) === null || _a === void 0 ? void 0 : _a.some((workspace) => 
        /* ignore coverage on optional-chaining */
        /* c8 ignore next */
        workspaces === null || workspaces === void 0 ? void 0 : workspaces.some((workspacePattern) => packageInfo.name === workspace ||
            packageInfo.filepath ===
                path_1.default.join(cwd, path_1.default.dirname(workspacePattern), workspace, defaultPackageFilename).replace(/\\/g, '/')));
    });
    return [selectedWorkspacePackageInfos, allWorkspacePackageNames];
}
/**
 * Gets all local packages, including workspaces (depending on -w, -ws, and -root).
 *
 * @param options the application options, used to determine which packages to return.
 * @returns PackageInfo[] an array of all package infos to be considered for updating
 */
async function getAllPackages(options) {
    const defaultPackageFilename = options.packageFile || 'package.json';
    const cwd = options.cwd ? (0, untildify_1.default)(options.cwd) : './';
    const rootPackageFile = options.packageFile || (options.cwd ? path_1.default.join(cwd, 'package.json') : 'package.json');
    const useWorkspaces = options.workspaces === true || (options.workspace !== undefined && options.workspace.length !== 0);
    let packageInfos = [];
    // Find the package file with globby.
    // When in workspaces mode, only include the root project package file when --root is used.
    const getBasePackageFile = !useWorkspaces || options.root === true;
    if (getBasePackageFile) {
        // we are either:
        // * NOT a workspace
        // * a workspace and have requested an upgrade of the workspace-root
        const globPattern = rootPackageFile.replace(/\\/g, '/');
        const rootPackagePaths = globby_1.default.sync(globPattern, {
            ignore: ['**/node_modules/**'],
        });
        // realistically there should only be zero or one
        const rootPackages = [
            ...(await Promise.all(rootPackagePaths.map(async (packagePath) => await (0, loadPackageInfoFromFile_1.default)(options, packagePath)))),
        ];
        packageInfos = [...packageInfos, ...rootPackages];
    }
    if (!useWorkspaces) {
        return [packageInfos, []];
    }
    // workspaces
    const [workspacePackageInfos, workspaceNames] = await getWorkspacePackageInfos(options, defaultPackageFilename, rootPackageFile, cwd);
    packageInfos = [...packageInfos, ...workspacePackageInfos];
    return [packageInfos, workspaceNames];
}
exports.default = getAllPackages;
//# sourceMappingURL=getAllPackages.js.map