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

@devstacks/packager

v0.20.2

Published

A versatile utility for archiving, compressing, and signing deployment files.

Downloads

12

Readme

@devstacks/packager

npm version License: MIT codecov

A robust utility for archiving, compressing, and signing web applications for cross-platform deployment. Built with TypeScript and designed for both CLI and programmatic usage.

Features

  • 📦 Archiving: Preserve directory structures with metadata
  • 🗜️ Compression: Multiple algorithms (GZIP, Brotli, DEFLATE)
  • 🔑 Cryptography: Ed25519 signing and verification
  • 🖥️ CLI: Intuitive command-line interface
  • ⚡ API: Fully typed, promise-based API
  • 🔒 Security: Built with security best practices
  • 📏 Validation: Comprehensive input validation with Zod

Table of Contents

Installation

Prerequisites

  • Node.js 18.0.0 or later
  • npm 7.0.0 or later

Global Installation

For CLI usage:

npm install -g @devstacks/packager

Project Installation

For programmatic usage:

npm install @devstacks/packager

Using with npx

For one-off usage without installation:

npx @devstacks/packager [command] [options]

Quick Start

  1. Create a package (archive + compress + sign):
# Generate a key pair first
packager generate-keys private.key public.key

# Create a package
packager package ./src ./dist/package.pkg --algorithm gzip --privkey private.key
  1. Use in your code:
import { createPackage, CompressionAlgorithm } from '@devstacks/packager';

// Create a package programmatically
await createPackage(
  './src',
  './dist/package.pkg',
  {
    algorithm: CompressionAlgorithm.GZIP,
    privateKeyPath: './private.key'
  }
);

CLI Usage

Archive Operations

Archive a Directory

# Basic usage
packager archive ./src ./output.archive

# With include/exclude patterns
packager archive ./src ./output.archive \
  --include "**/*.html,**/*.js,**/*.css" \
  --exclude "**/*.map,**/node_modules/**,**/.git/**"

# Shorthand
packager a ./src ./output.archive

Unarchive a File

packager unarchive ./output.archive ./extracted-files

Compression Operations

Compress a File

# Basic compression
packager compress input.txt output.txt.gz

# With specific algorithm and level (1-9)
packager compress input.txt output.txt.gz --algorithm gzip --level 9

# Archive directory before compressing
packager compress ./src output.pkg --archive

# Shorthand
packager c input.txt output.txt.gz

Decompress a File

# Basic decompression
packager decompress input.txt.gz output.txt

# Auto-detect algorithm
packager decompress input.compressed output.file

# Shorthand
packager d input.txt.gz output.txt

Cryptography Operations

Generate Key Pair

# Generate Ed25519 key pair
packager generate-keys private.key public.key

# Shorthand
packager g private.key public.key

Sign a File

# Sign a file
packager sign file.txt file.txt.sig --privkey private.key

# Shorthand
packager s file.txt file.txt.sig --privkey private.key

Verify a Signature

# Verify a signature
packager verify file.txt file.txt.sig --pubkey public.key

# Shorthand
packager v file.txt file.txt.sig --pubkey public.key

Complete Packaging

Create a complete package (archive + compress + sign) in one command:

# Basic package
packager package ./src ./dist/package.pkg --algorithm gzip --privkey private.key

# Shorthand
packager pkg ./src ./dist/package.pkg --algorithm gzip --privkey private.key

# Using the 'acs' shorthand (archive + compress + sign)
packager acs ./src ./dist/package.pkg --algorithm gzip --privkey private.key

# With include/exclude patterns
packager acs ./src ./dist/package.pkg \
  --algorithm gzip \
  --privkey private.key \
  --include "**/*.html,**/*.js,**/*.css" \
  --exclude "**/*.map"

API Reference

Archive

archiveDirectory(sourcePath: string, outputPath: string, options?: ArchiveOptions): Promise<void>

Archives a directory to a file.

import { archiveDirectory } from '@devstacks/packager';

await archiveDirectory('./src', './output.archive', {
  include: ['**/*.js', '**/*.json'],
  exclude: ['**/node_modules/**', '**/.git/**']
});

Options:

  • include: Array of glob patterns to include
  • exclude: Array of glob patterns to exclude

unarchiveFile(archivePath: string, outputPath: string): Promise<void>

Extracts an archive to a directory.

import { unarchiveFile } from '@devstacks/packager';

await unarchiveFile('./output.archive', './extracted');

Compression

compressFile(sourcePath: string, outputPath: string, options: CompressionOptions): Promise<void>

Compresses a file using the specified algorithm.

import { compressFile, CompressionAlgorithm } from '@devstacks/packager';

await compressFile('./input.txt', './output.txt.gz', {
  algorithm: CompressionAlgorithm.GZIP,
  level: 9
});

Options:

  • algorithm: Compression algorithm (GZIP, BROTLI, or DEFLATE)
  • level: Compression level (1-9, higher is better compression but slower)

decompressFile(sourcePath: string, outputPath: string, options?: { algorithm?: CompressionAlgorithm }): Promise<void>

Decompresses a file.

import { decompressFile } from '@devstacks/packager';

await decompressFile('./input.txt.gz', './output.txt');

Cryptography

generateAndSaveKeyPair(options: KeyPairOptions): Promise<void>

Generates and saves an Ed25519 key pair.

import { generateAndSaveKeyPair } from '@devstacks/packager';

await generateAndSaveKeyPair({
  privateKeyPath: './private.key',
  publicKeyPath: './public.key'
});

signFile(sourcePath: string, outputPath: string, options: SignOptions): Promise<void>

Signs a file.

import { signFile } from '@devstacks/packager';

await signFile('./input.txt', './input.txt.sig', {
  privateKeyPath: './private.key'
});

verifyFile(filePath: string, signaturePath: string, options: VerifyOptions): Promise<boolean>

Verifies a file's signature.

import { verifyFile } from '@devstacks/packager';

const isValid = await verifyFile(
  './input.txt',
  './input.txt.sig',
  { publicKeyPath: './public.key' }
);

Utilities

createPackage(sourcePath: string, outputPath: string, options: PackageOptions): Promise<void>

Creates a complete package (archive + compress + sign).

import { createPackage, CompressionAlgorithm } from '@devstacks/packager';

await createPackage(
  './src',
  './dist/package.pkg',
  {
    algorithm: CompressionAlgorithm.GZIP,
    privateKeyPath: './private.key',
    include: ['**/*.js', '**/*.json'],
    exclude: ['**/node_modules/**']
  }
);

Error Handling

All API functions throw typed errors that extend the native Error class. Always use try/catch blocks:

try {
  await createPackage('./src', './dist/package.pkg', {
    algorithm: CompressionAlgorithm.GZIP,
    privateKeyPath: './private.key'
  });
} catch (error) {
  console.error('Package creation failed:', error.message);
  if (error.code === 'ENOENT') {
    console.error('File not found:', error.path);
  }
}

Performance

Compression Algorithms

| Algorithm | Best For | Compression | Speed | Native Support | |-----------|----------|-------------|-------|----------------| | GZIP | General use | Good | Fast | Widely supported | | Brotli | Web content | Excellent | Medium | Modern browsers | | DEFLATE | Legacy systems | Good | Fast | Universal |

Memory Usage

For large files, consider streaming or chunking to manage memory usage. The library handles files larger than memory by default.

Security

Key Management

  • Always store private keys securely (never commit them to version control)
  • Use environment variables for sensitive data:
export PRIVATE_KEY_PATH="/path/to/private.key"
packager sign file.txt file.txt.sig --privkey "$PRIVATE_KEY_PATH"

Best Practices

  1. Always verify signatures before processing untrusted files
  2. Use strong compression levels (6-9) for sensitive data
  3. Keep your dependencies up to date
  4. Use the latest version of Node.js with security patches

Development

Setup

git clone https://github.com/devstacks-software-engineering/packager.git
cd packager/base
npm install

Building

npm run build

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run linting
npm run lint

# Run type checking
npm run typecheck

Local Development

Link the package for local development:

# Build and link
npm run build
npm link

# Now you can use it globally
packager --version

Contributing

Contributions are welcome! Please read our Contributing Guidelines before submitting pull requests.

License

MIT © DevStacks CompressionAlgorithm.GZIP, { privateKeyPath: '/path/to/private.key' } );


## Archive Format

The archive format is designed to be simple, efficient, and extensible:

- **Header**: Contains signature, version, and number of entries
- **Entry Table**: Contains offsets and sizes for each entry
- **Entry Data**: Contains metadata (path, size, MIME type) and file data

## Compression Algorithms

The packager supports multiple compression algorithms. The choice of algorithm can impact both the size of the compressed data and the performance of compression and decompression. Native platform support for decompression is a key factor in selecting an algorithm for optimal performance.

### **DEFLATE**

* **Description:**
    * A lossless data compression algorithm that uses a combination of LZ77 and Huffman coding. It is the core algorithm for GZIP and ZIP.
* **Best For Compression:**
    * Good balance between compression ratio and speed; scenarios requiring low overhead.
* **Native Decompression Support & Best Fit for Decompression:**
    * **Windows (C#/.NET):**
        * Native support via `System.IO.Compression.DeflateStream`.
        * Fits well when decompressing data from GZIP or ZIP archives, or when a lightweight, fast decompression is needed.
    * **Linux (Python with GTK):**
        * Native support via the `zlib` standard library.
        * Excellent fit for general-purpose decompression where `zlib` is readily available.
    * **Android (Java/Kotlin):**
        * Native support via `java.util.zip.InflaterInputStream` or `java.util.zip.Inflater`.
        * A good choice for decompressing ZIP files or raw DEFLATE streams.
    * **iOS/macOS (Swift):**
        * Native support via Apple's Compression framework (using `Algorithm.zlib` or the C-level `COMPRESSION_ZLIB`).
        * Ideal for decompressing raw DEFLATE streams or as the core for handling GZIP/ZIP data.


### **GZIP**

* **Description:**
    * Based on DEFLATE, it adds a header and trailer with metadata, including a CRC32 checksum for error detection. Good compression ratio and widely compatible.
* **Best For Compression:**
    * General-purpose usage, especially for web content and file transfer where compatibility and integrity checks are valued.
* **Native Decompression Support & Best Fit for Decompression:**
    * **Windows (C#/.NET):**
        * Native support via `System.IO.Compression.GZipStream`.
        * Ideal for decompressing `.gz` files or HTTP content encoded with GZIP.
    * **Linux (Python with GTK):**
        * Native support via the `gzip` and `zlib` standard libraries.
        * Widely used and fits well for decompressing files and web data.
    * **Android (Java/Kotlin):**
        * Native support via `java.util.zip.GZIPInputStream`.
        * Commonly used for decompressing web responses and `.gz` files.
    * **iOS/macOS (Swift):**
        * Native support by using Apple's Compression framework with `Algorithm.zlib` (DEFLATE) and manually handling GZIP headers/trailers, or by leveraging common system libraries that wrap zlib for GZIP.
        * Fits well for decompressing `.gz` files and GZIP-encoded web data.


### **BROTLI**

* **Description:**
    * A modern algorithm offering better compression ratios than GZIP, especially for text-based data.
* **Best For Compression:**
    * When compression ratio is the highest priority, particularly for static web assets like HTML, CSS, and JavaScript.
* **Native Decompression Support & Best Fit for Decompression:**
    * **Windows (C#/.NET):**
        * Native support available (e.g., `System.IO.Compression.BrotliStream` in .NET Core/5+).
        * Best fit for decompressing Brotli-encoded web content or assets where the .NET runtime provides built-in support.
    * **Linux (Python with GTK):**
        * Native decompression typically requires external libraries (e.g., `brotli` PyPI package).
        * Fits best when the environment is set up with these dependencies and maximum decompression ratio benefits are sought.
    * **Android (Java/Kotlin):**
        * Native support is less direct for general app development compared to DEFLATE/GZIP; often available via WebView for web content or through JNI with Brotli libraries.
        * Best fit for decompressing Brotli-encoded content within web contexts or when specifically integrating a Brotli library.
    * **iOS/macOS (Swift):**
        * Native support via Apple's Compression framework (using `Algorithm.brotli` or C-level `COMPRESSION_BROTLI`, available iOS 13+/macOS 10.15+; C API availability might be iOS 15+ for some uses, requiring OS version checks).
        * Excellent for decompressing Brotli-encoded web content and text-heavy data directly within apps.


## Cryptography

The packager uses Ed25519 for digital signatures, which offers:

- **Small key sizes**: 32-byte public keys, 64-byte signatures
- **Fast verification**: 50-70x faster than RSA
- **High security**: Resistant to side-channel attacks

## License

MIT