import fs from 'node:fs';
import { path } from "./path.js";
import { flist, log_action } from "./file.js";
import { noprint } from "./process.js";
import { WritableMemoryStream, check } from "./utils.js";
/** 将文件夹或文件列表压缩为 zip，返回生成的压缩包路径 (fp_zip)
    - data:
        - fpd_src: 被压缩文件夹路径 (string) 或
        - entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
    - fp_zip: 生成的压缩包路径 (string)
    - options?:
        - dirname?: `fpd_src.fname` 传入 fpd_src 才生效，修改 zip 中顶层的文件夹的名字（需要以 / 结尾），如 'web/', 为空字符串时去掉顶层文件夹，不要多一个文件夹层级 (flat)
        - print?:
            - info?: `true` 开始压缩、压缩完成
            - files?: `true` 打印压缩文件列表 */
export async function fzip(data, fp_zip, options) {
    return _zip(data, fp_zip, options);
}
/** 将文件夹或文件列表压缩为 zip，返回压缩包数据 (Uint8Array)
    - data:
        - fpd_src: 被压缩文件夹路径 (string) 或
        - entries: 文件列表 (Record<压缩后相对路径, 原文件绝对路径 (string) | 数据 (Uint8Array)>)
    - options?:
        - dirname?: `fpd_src.fname` 传入 fpd_src 才生效，修改 zip 中顶层的文件夹的名字（需要以 / 结尾），如 'web/', 为空字符串时去掉顶层文件夹，不要多一个文件夹层级 (flat)
        - print?:
            - info?: `true` 开始压缩、压缩完成
            - files?: `true` 打印压缩文件列表 */
export async function zip(data, options) {
    return _zip(data, undefined, options);
}
async function _zip(data, fp_zip, { dirname, print = { files: true, info: true } } = {}) {
    let entries;
    let fpd_src;
    if (typeof data === 'string') {
        if (!path.isAbsolute(data) || !data.isdir)
            throw new Error('fpd_src 必须是绝对路径且以 / 结尾');
        fpd_src = data;
        if (dirname === undefined)
            dirname = fpd_src.fname;
        if (!dirname.isdir)
            throw new Error('dirname 需要以 / 结尾');
        entries = Object.fromEntries((await flist(fpd_src, noprint))
            .map(fp => ([dirname + fp, fpd_src + fp])));
    }
    else {
        check(!dirname, 'dirname 在传入 fpd_src 时才生效');
        entries = data;
    }
    if (print.info)
        log_action('开始压缩', fpd_src ? ` ${fpd_src}` : '文件索引', fp_zip ? `${fp_zip}/${dirname || '{entries}'}` : '内存');
    const { default: archiver } = await import('archiver');
    let archive = archiver('zip');
    let ostream = fp_zip ?
        fs.createWriteStream(fp_zip, { highWaterMark: 16 * 2 ** 20 /* 16 MB */ })
        :
            new WritableMemoryStream();
    const size = await new Promise(async (resolve, reject) => {
        ostream.once('close', () => {
            resolve(archive.pointer());
        });
        ostream.once('error', reject);
        archive.once('error', reject);
        archive.on('warning', error => {
            console.log(error);
        });
        archive.pipe(ostream);
        for (const fp in entries) {
            const fdata = entries[fp];
            if (fdata instanceof Uint8Array) {
                if (print.files)
                    log_action('压缩', fdata.length.to_fsize_str(), fp);
                archive.append(Buffer.isBuffer(fdata) ? fdata : Buffer.from(fdata.buffer), { name: fp });
            }
            else {
                check(fp.isdir === fdata.isdir);
                check(path.isAbsolute(fdata));
                if (print.files)
                    log_action('压缩', fdata, fp);
                if (fp.isdir)
                    archive.directory(fdata, fp);
                else
                    archive.file(fdata, { name: fp });
            }
        }
        await archive.finalize();
    });
    if (print.info)
        console.log(`压缩完成，总大小 ${size.to_fsize_str()}`);
    return fp_zip || ostream.pbuffer;
}
//# sourceMappingURL=fzip.js.map