201
}
202
203
>
export async function zip(zipPath: string, files: IFile[]): Promise<string> {
zip.ts
204
>
const { ZipFile } = await import('yazl');
205
>
206
>
const zip = new ZipFile();
207
>
const zipStream = createWriteStream(zipPath);
208
>
209
>
// Attach error/finish handling before adding entries so a read stream that
210
>
// errors while a later entry is still awaiting I/O has a listener.
211
>
const result = new Promise<string>((c, e) => {
212
>
zip.outputStream.once('error', e);
213
>
zipStream.once('error', e);
214
>
zipStream.once('finish', () => c(zipPath));
215
>
});
216
>
zip.outputStream.pipe(zipStream);
217
>
218
>
for (const f of files) {
219
>
if (f.contents !== undefined) {
220
zip.addBuffer(typeof f.contents === 'string' ? Buffer.from(f.contents, 'utf8') : f.contents, f.path);
221
>
} else if (f.localPath) {
zip.ts
222
>
if (f.localPathSize === undefined) {
223
zip.addFile(f.localPath, f.path);
225
>
// yazl aborts the archive unless the streamed byte count matches the
226
>
// declared size. Derive both from a single handle so the counts match
227
>
// even if the path is rotated or truncated concurrently; skip a
228
>
// vanished file rather than failing the whole archive.
229
>
let handle: FileHandle;
230
>
try {
231
>
handle = await promises.open(f.localPath, 'r');
232
>
} catch (error) {
233
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
234
continue;