"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const rimraf = require("@zkochan/rimraf");
const fs = require("mz/fs");
const pLimit = require("p-limit");
const ssri = require("ssri");
const getFilePathInCafs_1 = require("./getFilePathInCafs");
const parseJson_1 = require("./parseJson");
const limit = pLimit(20);
const MAX_BULK_SIZE = 1 * 1024 * 1024; // 1MB
async function default_1(cafsDir, pkgIndex, manifest) {
    let verified = true;
    await Promise.all(Object.keys(pkgIndex)
        .map((f) => limit(async () => {
        const fstat = pkgIndex[f];
        if (!fstat.integrity) {
            throw new Error(`Integrity checksum is missing for ${f}`);
        }
        if (!await verifyFile(getFilePathInCafs_1.getFilePathByModeInCafs(cafsDir, fstat.integrity, fstat.mode), fstat, f === 'package.json' ? manifest : undefined)) {
            verified = false;
        }
    })));
    return verified;
}
exports.default = default_1;
async function verifyFile(filename, fstat, deferredManifest) {
    if (fstat.size > MAX_BULK_SIZE && !deferredManifest) {
        try {
            const ok = Boolean(await ssri.checkStream(fs.createReadStream(filename), fstat.integrity));
            if (!ok) {
                await rimraf(filename);
            }
            return ok;
        }
        catch (err) {
            switch (err.code) {
                case 'ENOENT': return false;
                case 'EINTEGRITY': {
                    // Broken files are removed from the store
                    await rimraf(filename);
                    return false;
                }
            }
            throw err;
        }
    }
    try {
        const data = await fs.readFile(filename);
        const ok = Boolean(ssri.checkData(data, fstat.integrity));
        if (!ok) {
            await rimraf(filename);
        }
        else if (deferredManifest) {
            parseJson_1.parseJsonBuffer(data, deferredManifest);
        }
        return ok;
    }
    catch (err) {
        switch (err.code) {
            case 'ENOENT': return false;
            case 'EINTEGRITY': {
                // Broken files are removed from the store
                await rimraf(filename);
                return false;
            }
        }
        throw err;
    }
}
//# sourceMappingURL=checkFilesIntegrity.js.map