"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path = require("path");
const fs_1 = require("fs");
const util_1 = require("./util");
/**
 * Finds the nearest package.json relative to the given directory, returning
 * undefined if it's not found.
 */
function findPackageJson(dir) {
    const parts = path.resolve(dir).split(path.sep);
    while (parts.length > 0) {
        const packagePath = [...parts, 'package.json'].join(path.sep);
        if (fs.existsSync(packagePath)) {
            return packagePath;
        }
        parts.pop();
    }
    return undefined;
}
exports.findPackageJson = findPackageJson;
/**
 * Loads data from the project's package.json, throwing an error if it can't
 * be loaded.
 */
function mustLoadPackageJson(dir) {
    const jsonPath = findPackageJson(dir);
    if (jsonPath) {
        return require(jsonPath); // tslint:disable-line
    }
    throw new Error('Could not find a package.json in your current folder, ' +
        'make sure to `cd` into your project directory!');
}
exports.mustLoadPackageJson = mustLoadPackageJson;
/**
 * Returns the base path of a project nested in the given directory (the
 * folder containing the package.json).
 */
function getProjectPath(dir) {
    const json = findPackageJson(dir);
    return json ? path.dirname(json) : undefined;
}
exports.getProjectPath = getProjectPath;
/**
 * Finds where the given dependency is installed.
 */
function getDependencyPath(name) {
    // require.resolve resolves to the main js script of the package, back out
    // to get its directory.
    const target = require.resolve(name).split(path.sep);
    while (target[target.length - 1] !== name) {
        target.pop();
    }
    return target.join(path.sep);
}
exports.getDependencyPath = getDependencyPath;
/**
 * Gets the path to the binary script defeined by the module in the given dir.
 */
function getPackageExecutable(base, commandName = path.basename(base)) {
    const parsed = mustLoadPackageJson(base);
    return path.join(base, parsed.bin[commandName]);
}
exports.getPackageExecutable = getPackageExecutable;
/**
 * Finds the readme for the project in the given directory. Uses a similar
 * process to npm.
 */
function findReadme(dir) {
    return __awaiter(this, void 0, void 0, function* () {
        const fname = (yield util_1.readDir(dir)).find(f => /^readme\.?/i.test(f));
        if (fname) {
            return fname;
        }
        try {
            const packageJson = mustLoadPackageJson(dir);
            return packageJson && path.normalize(packageJson.readmeFile);
        }
        catch (e) {
            return undefined;
        }
    });
}
exports.findReadme = findReadme;
/**
 * Returns whether all requested dependencies are installed in node_modules
 * relative to the project base directory.
 */
function isPackagedInstalled(baseDir, ...dependencies) {
    return __awaiter(this, void 0, void 0, function* () {
        return !dependencies.some(dep => !fs_1.existsSync(path.join(baseDir, 'node_modules', dep)));
    });
}
exports.isPackagedInstalled = isPackagedInstalled;
