npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

picozip

v0.0.1

Published

A truly cross platform zip library designed for memory limited environment, fully written in JS using modern standard JS APIs.

Readme

picozip

A truly cross platform zip library designed for memory limited environment, fully written in JS using modern standard JS APIs. The core library has no dependencies and uses no Node.js modules.

This is still a work in progress and breaking API change is very likely until stable release.

Usage

The core part of the library is the Zip class.

import { Zip } from "picozip";

The Zip class can be created with the constructor or with the static open() method.

const zip1 = new Zip("file.zip", fetcher);
await zip1.open();

const zip2 = await Zip.open("file.zip", fetcher);

The difference between the two is that the former does not make any request on creation and will wait until open() is called on the object while the latter both create the object and call open() on it in one pass.

fetcher is a function that matches the signature defined by the RangeFetcher export.

type RangeFetcher = (
  key: string,
  options: { start: number; end?: number },
) => Promise<ReadableStream>;

key is the path to the zip file as interpreted by the fetcher and options is the range in which to fetch the partial content. start can be either positive or negative while end is optional. The range works in the same way as HTTP Range header, meaning they represent bytes, is zero-index, and both indexes are inclusive (ie. in the range of [start, end], not [start, end) as is typical of array slice operations).

Once the zip file has been opened, the entries property will consist of an array of all files and folders stored in the zip file. A better way of navigating the zip file will be implemented in the future. To get a specific file from the zip file:

const file = zip.file("content.txt");

To read the contents of the file, you can obtain either a ReadableStream or an ArrayBuffer from it:

const stream = await file.getStream();

// OR

const buffer = await file.getArrayBuffer();

Either method will consume the underlying ReadableStream so you cannot call both together.

Limitations

Currently only unzip operation is supported. Zip functionality will be implemented later.

CRC32 checksums are currently not checked as part of the unzipping process.

The process of opening and reading from a zip file will cause several requests being made through the fetcher for partial data. If requests count is a significant bottleneck for you (because of limitation on number of request or latency), you can either buffer the entire file for a fetcher if memory is not a limitation, or you may need to find another solution.

Why

The initial motivation for this library is to have an unzip utility that can work in Cloudflare Workers that can selectively stream files from a very large zip files. Cloudflare workers only have 128MB of RAM, a worker exceeding that could be evicted and exit. This means it cannot load the whole zip file into memory or load file out of it into memory if either exceeds 128MB. Using a streaming API is the recommended way to work with large files.

However, existing libraries either expect to work off a zip buffer that is fully loaded into memory already or if they do have streaming API, is designed to work in Node.js only or only read and write files to the file system.

Zip itself is not a very complex format and it is fairly simple to implement something that can read the internal file records and since each file is compressed and stored separately, they can be extracted on their own without needing to read any other file that is not needed. Two aspects of the zip format probably contributes to the shortcomings of existing implementations:

1. The central directory where canonical data about what is in the zip file is stored at the end of the zip file.

This is sturctured this way because it enables the zip format to add or remove files from the zip file by just appending to the end of the file while not editing any other parts of the file. However if one does not have a way to read from the end of the zip file, then they will have to read from the start all the way to the end to find the central directory.

2. For a time JS did not have a standard way of decompressing data from zip file.

Node.js provides the node:zlib built-in package to help handle this and the assumption is thus made that other environments like the browser either need a from scratch implementation of the decompression algorithm or have no way of decompressing. It doesn't help that many of the existing libraries were written quite some time ago and has not received updates for years.

Modern JS however already have all the tools required to solved these problems. Reading data from the end of the files have always been possible with HTTP Range header, Node.js fs.createReadStream, S3 API, etc. Unless there is a risk of the file changing in the original source mid-decompression, this should not be an issue.

Decompressing data is now also possible with the DecompressionStream API. It is supported by practically all modern browsers and all modern JS runtime. This means that rather than using node:zlib, bundling a WASM bundle, or use a pure JS implementation, the JS runtime itself will have the tools to decompress data within a zip file already, implemented with native performance.

Add all these with the standard ReadableStream API, we have something that can load parts of a zip file, decompress data from it, and pipe it all through streams without needing to buffer anything in our limited RAM.

Development

  • Install dependencies:
vp install
  • Run the unit tests:
vp test
  • Build the library:
vp pack