"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 getCredentialsByURI = require("credentials-by-uri");
const fetch_from_npm_registry_1 = require("fetch-from-npm-registry");
const mem = require("mem");
const ssri = require("ssri");
const createNpmPkgId_1 = require("./createNpmPkgId");
const parsePref_1 = require("./parsePref");
const pickPackage_1 = require("./pickPackage");
const toRaw_1 = require("./toRaw");
// This file contains meta information
// about all the packages published by the same name, not just the manifest
// of one package/version
const META_FILENAME = 'index.json';
const FULL_META_FILENAME = 'index-full.json';
function createResolver(opts) {
    if (typeof opts.rawNpmConfig !== 'object') {
        throw new TypeError('`opts.rawNpmConfig` is required and needs to be an object');
    }
    if (typeof opts.rawNpmConfig['registry'] !== 'string') { // tslint:disable-line
        throw new TypeError('`opts.rawNpmConfig.registry` is required and needs to be a string');
    }
    if (typeof opts.metaCache !== 'object') {
        throw new TypeError('`opts.metaCache` is required and needs to be an object');
    }
    if (typeof opts.store !== 'string') {
        throw new TypeError('`opts.store` is required and needs to be a string');
    }
    const fetch = fetch_from_npm_registry_1.default({
        ca: opts.ca,
        cert: opts.cert,
        fullMetadata: opts.fullMetadata,
        key: opts.key,
        localAddress: opts.localAddress,
        proxy: opts.httpsProxy || opts.proxy,
        retry: {
            factor: opts.fetchRetryFactor,
            maxTimeout: opts.fetchRetryMaxtimeout,
            minTimeout: opts.fetchRetryMintimeout,
            retries: opts.fetchRetries,
        },
        strictSSL: opts.strictSsl,
        userAgent: opts.userAgent,
    });
    return resolveNpm.bind(null, {
        getCredentialsByURI: mem((registry) => getCredentialsByURI(registry, opts.rawNpmConfig)),
        pickPackage: pickPackage_1.default.bind(null, {
            fetch,
            metaCache: opts.metaCache,
            metaFileName: opts.fullMetadata ? FULL_META_FILENAME : META_FILENAME,
            offline: opts.offline,
            preferOffline: opts.preferOffline,
            storePath: opts.store,
        }),
    });
}
exports.default = createResolver;
function resolveNpm(ctx, wantedDependency, opts) {
    return __awaiter(this, void 0, void 0, function* () {
        const spec = wantedDependency.pref
            ? parsePref_1.default(wantedDependency.pref, wantedDependency.alias, opts.defaultTag || 'latest')
            : defaultTagForAlias(wantedDependency.alias, opts.defaultTag || 'latest');
        if (!spec)
            return null;
        const auth = ctx.getCredentialsByURI(opts.registry);
        const pickResult = yield ctx.pickPackage(spec, {
            auth,
            dryRun: opts.dryRun === true,
            preferredVersionSelector: opts.preferredVersions && opts.preferredVersions[spec.name],
            registry: opts.registry,
        });
        const pickedPackage = pickResult.pickedPackage;
        const meta = pickResult.meta;
        if (!pickedPackage) {
            const versions = Object.keys(meta.versions);
            const err = new Error(`No matching version found for ${toRaw_1.default(spec)}`);
            // tslint:disable:no-string-literal
            err['code'] = 'ERR_PNPM_NO_MATCHING_VERSION';
            err['packageMeta'] = meta;
            // tslint:enable:no-string-literal
            throw err;
        }
        const id = createNpmPkgId_1.default(pickedPackage.dist.tarball, pickedPackage.name, pickedPackage.version);
        const resolution = {
            integrity: getIntegrity(pickedPackage.dist),
            registry: opts.registry,
            tarball: pickedPackage.dist.tarball,
        };
        return {
            id,
            latest: meta['dist-tags'].latest,
            package: pickedPackage,
            resolution,
            resolvedVia: 'npm-registry',
        };
    });
}
function defaultTagForAlias(alias, defaultTag) {
    return {
        fetchSpec: defaultTag,
        name: alias,
        type: 'tag',
    };
}
function getIntegrity(dist) {
    if (dist.integrity) {
        return dist.integrity;
    }
    return ssri.fromHex(dist.shasum, 'sha1').toString();
}
//# sourceMappingURL=index.js.map