"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 dp = require("dependency-path");
const npa = require("npm-package-arg");
const RegClient = require("npm-registry-client");
const package_store_1 = require("package-store");
const pnpm_logger_1 = require("pnpm-logger");
const pnpm_shrinkwrap_1 = require("pnpm-shrinkwrap");
const depTypes = ['dependencies', 'devDependencies', 'optionalDependencies'];
function default_1(pkgPath, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        return _outdated([], pkgPath, opts);
    });
}
exports.default = default_1;
function forPackages(packages, pkgPath, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        return _outdated(packages, pkgPath, opts);
    });
}
exports.forPackages = forPackages;
function _outdated(forPkgs, pkgPath, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        const wantedShrinkwrap = yield pnpm_shrinkwrap_1.readWanted(pkgPath, { ignoreIncompatible: false });
        if (!wantedShrinkwrap) {
            throw new Error('No shrinkwrapfile in this directory. Run `pnpm install` to generate one.');
        }
        const storePath = yield package_store_1.resolveStore(opts.store, pkgPath);
        const currentShrinkwrap = (yield pnpm_shrinkwrap_1.readCurrent(pkgPath, { ignoreIncompatible: false })) || {};
        const client = new RegClient(adaptConfig(opts));
        const got = package_store_1.createGot(client, {
            alwaysAuth: opts.alwaysAuth,
            factor: opts.fetchRetryFactor,
            maxTimeout: opts.fetchRetryMaxtimeout,
            minTimeout: opts.fetchRetryMintimeout,
            networkConcurrency: opts.networkConcurrency,
            rawNpmConfig: opts.rawNpmConfig,
            registry: wantedShrinkwrap.registry,
            retries: opts.fetchRetries,
        });
        const metaCache = new Map();
        const outdated = [];
        yield Promise.all(depTypes.map((depType) => __awaiter(this, void 0, void 0, function* () {
            if (!wantedShrinkwrap[depType])
                return;
            let pkgs = Object.keys(wantedShrinkwrap[depType]);
            if (forPkgs.length) {
                pkgs = pkgs.filter((pkgName) => forPkgs.indexOf(pkgName) !== -1);
            }
            yield Promise.all(pkgs.map((packageName) => __awaiter(this, void 0, void 0, function* () {
                const ref = wantedShrinkwrap[depType][packageName];
                const relativeDepPath = dp.refToRelative(ref, packageName);
                const pkgSnapshot = wantedShrinkwrap.packages && wantedShrinkwrap.packages[relativeDepPath];
                if (!pkgSnapshot) {
                    throw new Error(`Invalid shrinkwrap.yaml file. ${relativeDepPath} not found in packages field`);
                }
                // It might be not the best solution to check for pkgSnapshot.name
                // TODO: add some other field to distinct packages not from the registry
                if (pkgSnapshot.resolution && (pkgSnapshot.resolution['type'] || pkgSnapshot.name)) {
                    if (currentShrinkwrap[depType][packageName] !== wantedShrinkwrap[depType][packageName]) {
                        outdated.push({
                            current: currentShrinkwrap[depType][packageName],
                            latest: undefined,
                            packageName,
                            wanted: wantedShrinkwrap[depType][packageName],
                        });
                    }
                    return;
                }
                const resolution = yield package_store_1.resolve(npa.resolve(packageName, 'latest'), {
                    downloadPriority: 0,
                    got,
                    loggedPkg: {
                        name: packageName,
                        rawSpec: `${packageName}@latest`,
                    },
                    metaCache,
                    offline: opts.offline,
                    prefix: pkgPath,
                    registry: wantedShrinkwrap.registry,
                    storePath,
                });
                if (!resolution || !resolution.package)
                    return;
                const latest = resolution.package.version;
                if (!currentShrinkwrap[depType][packageName]) {
                    outdated.push({
                        latest,
                        packageName,
                        wanted: wantedShrinkwrap[depType][packageName],
                    });
                    return;
                }
                if (currentShrinkwrap[depType][packageName] !== wantedShrinkwrap[depType][packageName] ||
                    latest !== currentShrinkwrap[depType][packageName]) {
                    outdated.push({
                        current: currentShrinkwrap[depType][packageName],
                        latest,
                        packageName,
                        wanted: wantedShrinkwrap[depType][packageName],
                    });
                }
            })));
        })));
        return outdated.sort((pkg1, pkg2) => pkg1.packageName.localeCompare(pkg2.packageName));
    });
}
function adaptConfig(opts) {
    const registryLog = pnpm_logger_1.default('registry');
    return {
        defaultTag: opts.tag,
        log: Object.assign({}, registryLog, {
            http: registryLog.debug.bind(null, 'http'),
            verbose: registryLog.debug.bind(null, 'http'),
        }),
        proxy: {
            http: opts.proxy,
            https: opts.httpsProxy,
            localAddress: opts.localAddress,
        },
        retry: {
            count: opts.fetchRetries,
            factor: opts.fetchRetryFactor,
            maxTimeout: opts.fetchRetryMaxtimeout,
            minTimeout: opts.fetchRetryMintimeout,
        },
        ssl: {
            ca: opts.ca,
            certificate: opts.cert,
            key: opts.key,
            strict: opts.strictSsl,
        },
        userAgent: opts.userAgent,
    };
}
//# sourceMappingURL=index.js.map