Skip to content

zip

Terminal window
bun add @stopcock/zip

Creates valid ZIP files with DEFLATE compression. Everything happens in memory, no filesystem needed.

import { createZip, type ZipEntry } from '@stopcock/zip'
const zip = createZip([
{ path: 'readme.txt', data: new TextEncoder().encode('hello') },
{ path: 'docs/notes.txt', data: new TextEncoder().encode('world') },
])
await Bun.write('archive.zip', zip)

Paths with / create nested directories in the archive.

interface ZipEntry {
path: string
data: Uint8Array
}
createZip(entries: ZipEntry[]): Uint8Array

createZip takes an array of entries, DEFLATE-compresses each one, writes local file headers + central directory + end record, and returns the complete ZIP as a Uint8Array.

Combine with @stopcock/async for concurrent downloads and stopcock for data transformation:

import { pipe, A, D } from '@stopcock/fp'
import { fromPromise, map, flatMap, mapAsync, run } from '@stopcock/async'
import { createZip } from '@stopcock/zip'
const download = (url: string, path: string) => pipe(
fromPromise(() => fetch(url)),
flatMap(res => fromPromise(() => res.arrayBuffer())),
map(buf => ({ path, data: new Uint8Array(buf) })),
)
const entries = await pipe(
files,
mapAsync(f => download(f.url, f.name).run(), 4),
run,
)
await Bun.write('bundle.zip', createZip(entries))