rollup-plugin-zipdir
Version:
Rollup plugin to zip the entire output directory
60 lines (52 loc) • 2.06 kB
JavaScript
import { green, bold } from 'colorette';
import { zip } from 'fflate';
import { filesize } from 'filesize';
import { mkdir, writeFile, readFile, readdir } from 'node:fs/promises';
import { sep, relative, basename, join } from 'node:path';
import { promisify } from 'node:util';
/**
* filetree-to-object method I adapted from https://stackoverflow.com/a/64092495/8396479
* @returns {Promise<object>}
*/
async function walkDir(dir) {
async function* tokenize(path) {
yield { dir: path };
for (const dirent of await readdir(path, { withFileTypes: true }))
if (dirent.isDirectory()) yield* tokenize(join(path, dirent.name));
else yield { file: join(path, dirent.name) };
yield { endDir: path };
}
const r = [{}];
for await (const e of tokenize(dir))
if (e.dir) r.unshift({});
else if (e.file) r[0][basename(e.file)] = await readFile(e.file);
else if (e.endDir) r[1][basename(e.endDir)] = r.shift();
return r[0][basename(dir)];
}
const parseFileName = function ({ name }) {
if (!!name) return name.endsWith('.zip') ? name : `${name}.zip`;
const { npm_package_name = 'bundle', npm_package_version } = process.env;
return !!npm_package_version ? `${npm_package_name}-${npm_package_version}.zip` : `${npm_package_name}.zip`;
};
function zipDir(options) {
return {
name: 'zipDir',
writeBundle: {
sequential: true,
order: 'post',
handler: async function (_options) {
const [output_dir, input_dir, name] = [
options?.outputDir ?? _options?.dir ?? process.cwd(),
_options?.dir ?? process.cwd(),
parseFileName(options),
];
const data = await promisify(zip)(await walkDir(input_dir));
//create dir if it does not exist
await mkdir(`.${sep}${relative(process.cwd(), output_dir)}`, { recursive: true });
await writeFile(`.${sep}${relative(process.cwd(), output_dir)}${sep}${name}`, data);
console.log(green(`zipped to ${bold(`${output_dir}${sep}${name}`)} (${filesize(data.byteLength)})`));
},
},
};
}
export { zipDir as default };