@plugjs/zip
Version:
Zip File Plugin for the PlugJS Build System ===========================================
59 lines (48 loc) • 1.98 kB
text/typescript
import { createWriteStream } from 'node:fs'
import { $p, $ylw, assert, Files } from '@plugjs/plug'
import { getAbsoluteParent } from '@plugjs/plug/paths'
import { ZipFile } from 'yazl'
import type { Context, PipeParameters, Plug } from '@plugjs/plug/pipe'
import type EventEmitter from 'node:events'
import type { ZipOptions } from '.'
// The "yazl" types don't define "ZipFile" as an "EventEmitter"
declare module 'yazl' {
interface ZipFile extends EventEmitter {
on(event: 'error', listener: (err: Error) => void): this;
}
}
/** Writes some info about the current {@link Files} being passed around. */
export class Zip implements Plug<Files> {
constructor(...args: PipeParameters<'zip'>)
constructor(
private readonly _filename: string,
private readonly _options: ZipOptions = {},
) {
assert(_filename, 'No filename specified for ZIP file')
}
pipe(files: Files, context: Context): Promise<Files> {
const filename = context.resolve(this._filename)
/* Create a new ZipFile piping to a WriteStream */
const zipfile = new ZipFile()
const zipstream = createWriteStream(filename)
zipfile.outputStream.pipe(zipstream)
/* Add all unique files to the zip */
context.log.info(`Packaging ${$ylw(files.length)} files`)
for (const [ relative, absolute ] of files.pathMappings()) {
context.log.debug(`Adding file ${$p(absolute)}`)
zipfile.addFile(absolute, relative, this._options)
}
/* All files are added, just compute our return */
const directory = getAbsoluteParent(filename)
const output = Files.builder(directory).add(filename).build()
zipfile.end()
/* When done, resolve or reject! */
return new Promise((resolve, reject) => {
zipstream.on('close', () => resolve(output))
/* coverage ignore next */
zipfile.on('error', (error) => reject(error))
/* coverage ignore next */
zipstream.on('error', (error) => reject(error))
})
}
}