mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
feat(archive): add TypeScript types, docs, and files() benchmark (#25922)
## Summary - Add comprehensive TypeScript type definitions for `Bun.Archive` in `bun.d.ts` - `ArchiveInput` and `ArchiveCompression` types - Full JSDoc documentation with examples for all methods (`from`, `write`, `extract`, `blob`, `bytes`, `files`) - Add documentation page at `docs/runtime/archive.mdx` - Quickstart examples - Creating and extracting archives - `files()` method with glob filtering - Compression support - Full API reference section - Add Archive to docs sidebar under "Data & Storage" - Add `files()` benchmark comparing `Bun.Archive.files()` vs node-tar - Shows ~7x speedup for reading archive contents into memory (59µs vs 434µs) ## Test plan - [x] TypeScript types compile correctly - [x] Documentation renders properly in Mintlify format - [x] Benchmark runs successfully and shows performance comparison - [x] Verified `files()` method works correctly with both Bun.Archive and node-tar 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
This commit is contained in:
290
packages/bun-types/bun.d.ts
vendored
290
packages/bun-types/bun.d.ts
vendored
@@ -6965,6 +6965,296 @@ declare module "bun" {
|
||||
match(str: string): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input data for creating an archive. Can be:
|
||||
* - An object mapping paths to file contents (string, Blob, TypedArray, or ArrayBuffer)
|
||||
* - A Blob containing existing archive data
|
||||
* - A TypedArray or ArrayBuffer containing existing archive data
|
||||
*/
|
||||
type ArchiveInput = Record<string, BlobPart> | Blob | ArrayBufferView | ArrayBufferLike;
|
||||
|
||||
/**
|
||||
* Compression format for archive output.
|
||||
* - `"gzip"` - Compress with gzip
|
||||
* - `true` - Same as `"gzip"`
|
||||
* - `false` - Explicitly disable compression (no compression)
|
||||
* - `undefined` - No compression (default behavior when omitted)
|
||||
*
|
||||
* Both `false` and `undefined` result in no compression; `false` can be used
|
||||
* to explicitly indicate "no compression" in code where the intent should be clear.
|
||||
*/
|
||||
type ArchiveCompression = "gzip" | boolean;
|
||||
|
||||
/**
|
||||
* Options for extracting archive contents.
|
||||
*/
|
||||
interface ArchiveExtractOptions {
|
||||
/**
|
||||
* Glob pattern(s) to filter which entries are extracted.
|
||||
* Uses the same syntax as {@link Bun.Glob}, including support for wildcards (`*`, `**`),
|
||||
* character classes (`[abc]`), alternation (`{a,b}`), and negation (`!pattern`).
|
||||
*
|
||||
* Patterns are matched against archive entry paths normalized to use forward slashes (`/`),
|
||||
* regardless of the host operating system. Always write patterns using `/` as the separator.
|
||||
*
|
||||
* - Positive patterns: Only entries matching at least one pattern will be extracted.
|
||||
* - Negative patterns (prefixed with `!`): Entries matching these patterns will be excluded.
|
||||
* Negative patterns are applied after positive patterns.
|
||||
*
|
||||
* If not specified, all entries are extracted.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Extract only TypeScript files
|
||||
* await archive.extract("./out", { glob: "**" + "/*.ts" });
|
||||
*
|
||||
* // Extract files from multiple directories
|
||||
* await archive.extract("./out", { glob: ["src/**", "lib/**"] });
|
||||
*
|
||||
* // Exclude node_modules using negative pattern
|
||||
* await archive.extract("./out", { glob: ["**", "!node_modules/**"] });
|
||||
*
|
||||
* // Extract source files but exclude tests
|
||||
* await archive.extract("./out", { glob: ["src/**", "!**" + "/*.test.ts"] });
|
||||
* ```
|
||||
*/
|
||||
glob?: string | readonly string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for creating and extracting tar archives with optional gzip compression.
|
||||
*
|
||||
* `Bun.Archive` provides a fast, native implementation for working with tar archives.
|
||||
* It supports creating archives from in-memory data or extracting existing archives
|
||||
* to disk or memory.
|
||||
*
|
||||
* @example
|
||||
* **Create an archive from an object:**
|
||||
* ```ts
|
||||
* const archive = Bun.Archive.from({
|
||||
* "hello.txt": "Hello, World!",
|
||||
* "data.json": JSON.stringify({ foo: "bar" }),
|
||||
* "binary.bin": new Uint8Array([1, 2, 3, 4]),
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Extract an archive to disk:**
|
||||
* ```ts
|
||||
* const archive = Bun.Archive.from(tarballBytes);
|
||||
* const entryCount = await archive.extract("./output");
|
||||
* console.log(`Extracted ${entryCount} entries`);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Get archive contents as a Map of File objects:**
|
||||
* ```ts
|
||||
* const archive = Bun.Archive.from(tarballBytes);
|
||||
* const entries = await archive.files();
|
||||
* for (const [path, file] of entries) {
|
||||
* console.log(path, await file.text());
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Write a gzipped archive directly to disk:**
|
||||
* ```ts
|
||||
* await Bun.Archive.write("bundle.tar.gz", {
|
||||
* "src/index.ts": sourceCode,
|
||||
* "package.json": packageJson,
|
||||
* }, "gzip");
|
||||
* ```
|
||||
*/
|
||||
export class Archive {
|
||||
/**
|
||||
* Create an `Archive` instance from input data.
|
||||
*
|
||||
* @param data - The input data for the archive:
|
||||
* - **Object**: Creates a new tarball with the object's keys as file paths and values as file contents
|
||||
* - **Blob/TypedArray/ArrayBuffer**: Wraps existing archive data (tar or tar.gz)
|
||||
*
|
||||
* @returns A new `Archive` instance
|
||||
*
|
||||
* @example
|
||||
* **From an object (creates new tarball):**
|
||||
* ```ts
|
||||
* const archive = Bun.Archive.from({
|
||||
* "hello.txt": "Hello, World!",
|
||||
* "nested/file.txt": "Nested content",
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **From existing archive data:**
|
||||
* ```ts
|
||||
* const response = await fetch("https://example.com/package.tar.gz");
|
||||
* const archive = Bun.Archive.from(await response.blob());
|
||||
* ```
|
||||
*/
|
||||
static from(data: ArchiveInput): Archive;
|
||||
|
||||
/**
|
||||
* Create and write an archive directly to disk in one operation.
|
||||
*
|
||||
* This is more efficient than creating an archive and then writing it separately,
|
||||
* as it streams the data directly to disk.
|
||||
*
|
||||
* @param path - The file path to write the archive to
|
||||
* @param data - The input data for the archive (same as `Archive.from()`)
|
||||
* @param compress - Optional compression: `"gzip"`, `true` for gzip, or `false`/`undefined` for none
|
||||
*
|
||||
* @returns A promise that resolves when the write is complete
|
||||
*
|
||||
* @example
|
||||
* **Write uncompressed tarball:**
|
||||
* ```ts
|
||||
* await Bun.Archive.write("output.tar", {
|
||||
* "file1.txt": "content1",
|
||||
* "file2.txt": "content2",
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Write gzipped tarball:**
|
||||
* ```ts
|
||||
* await Bun.Archive.write("output.tar.gz", files, "gzip");
|
||||
* ```
|
||||
*/
|
||||
static write(path: string, data: ArchiveInput | Archive, compress?: ArchiveCompression): Promise<void>;
|
||||
|
||||
/**
|
||||
* Extract the archive contents to a directory on disk.
|
||||
*
|
||||
* Creates the target directory and any necessary parent directories if they don't exist.
|
||||
* Existing files will be overwritten.
|
||||
*
|
||||
* @param path - The directory path to extract to
|
||||
* @param options - Optional extraction options
|
||||
* @param options.glob - Glob pattern(s) to filter entries (positive patterns include, negative patterns starting with `!` exclude)
|
||||
* @returns A promise that resolves with the number of entries extracted (files, directories, and symlinks)
|
||||
*
|
||||
* @example
|
||||
* **Extract all entries:**
|
||||
* ```ts
|
||||
* const archive = Bun.Archive.from(tarballBytes);
|
||||
* const count = await archive.extract("./extracted");
|
||||
* console.log(`Extracted ${count} entries`);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Extract only TypeScript files:**
|
||||
* ```ts
|
||||
* const count = await archive.extract("./src", { glob: "**" + "/*.ts" });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Extract everything except tests:**
|
||||
* ```ts
|
||||
* const count = await archive.extract("./dist", { glob: ["**", "!**" + "/*.test.*"] });
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Extract source files but exclude tests:**
|
||||
* ```ts
|
||||
* const count = await archive.extract("./output", {
|
||||
* glob: ["src/**", "lib/**", "!**" + "/*.test.ts", "!**" + "/__tests__/**"]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
extract(path: string, options?: ArchiveExtractOptions): Promise<number>;
|
||||
|
||||
/**
|
||||
* Get the archive contents as a `Blob`.
|
||||
*
|
||||
* @param compress - Optional compression: `"gzip"`, `true` for gzip, or `false`/`undefined` for none
|
||||
* @returns A promise that resolves with the archive data as a Blob
|
||||
*
|
||||
* @example
|
||||
* **Get uncompressed tarball:**
|
||||
* ```ts
|
||||
* const blob = await archive.blob();
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Get gzipped tarball:**
|
||||
* ```ts
|
||||
* const gzippedBlob = await archive.blob("gzip");
|
||||
* ```
|
||||
*/
|
||||
blob(compress?: ArchiveCompression): Promise<Blob>;
|
||||
|
||||
/**
|
||||
* Get the archive contents as a `Uint8Array`.
|
||||
*
|
||||
* @param compress - Optional compression: `"gzip"`, `true` for gzip, or `false`/`undefined` for none
|
||||
* @returns A promise that resolves with the archive data as a Uint8Array
|
||||
*
|
||||
* @example
|
||||
* **Get uncompressed tarball bytes:**
|
||||
* ```ts
|
||||
* const bytes = await archive.bytes();
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Get gzipped tarball bytes:**
|
||||
* ```ts
|
||||
* const gzippedBytes = await archive.bytes("gzip");
|
||||
* ```
|
||||
*/
|
||||
bytes(compress?: ArchiveCompression): Promise<Uint8Array<ArrayBuffer>>;
|
||||
|
||||
/**
|
||||
* Get the archive contents as a `Map` of `File` objects.
|
||||
*
|
||||
* Each file in the archive is returned as a `File` object with:
|
||||
* - `name`: The file path within the archive
|
||||
* - `lastModified`: The file's modification time from the archive
|
||||
* - Standard Blob methods (`text()`, `arrayBuffer()`, `stream()`, etc.)
|
||||
*
|
||||
* Only regular files are included; directories are not returned.
|
||||
* File contents are loaded into memory, so for large archives consider using `extract()` instead.
|
||||
*
|
||||
* @param glob - Optional glob pattern(s) to filter files. Supports the same syntax as {@link Bun.Glob},
|
||||
* including negation patterns (prefixed with `!`). Patterns are matched against paths normalized
|
||||
* to use forward slashes (`/`).
|
||||
* @returns A promise that resolves with a Map where keys are file paths (always using forward slashes `/` as separators) and values are File objects
|
||||
*
|
||||
* @example
|
||||
* **Get all files:**
|
||||
* ```ts
|
||||
* const entries = await archive.files();
|
||||
* for (const [path, file] of entries) {
|
||||
* console.log(`${path}: ${file.size} bytes`);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Filter by glob pattern:**
|
||||
* ```ts
|
||||
* const tsFiles = await archive.files("**" + "/*.ts");
|
||||
* const srcFiles = await archive.files(["src/**", "lib/**"]);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Exclude files with negative patterns:**
|
||||
* ```ts
|
||||
* // Get all source files except tests
|
||||
* const srcFiles = await archive.files(["src/**", "!**" + "/*.test.ts"]);
|
||||
* ```
|
||||
*
|
||||
* @example
|
||||
* **Read file contents:**
|
||||
* ```ts
|
||||
* const entries = await archive.files();
|
||||
* const readme = entries.get("README.md");
|
||||
* if (readme) {
|
||||
* console.log(await readme.text());
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
files(glob?: string | readonly string[]): Promise<Map<string, File>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a UUIDv7, which is a sequential ID based on the current timestamp with a random component.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user