### Browser Setup with Bundler and Workers Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md This example demonstrates a complete setup for browser environments using a bundler. It configures workers using a URL and utilizes HTTPRangeReader for efficient streaming of zip archives. ```javascript import { unzip, setOptions, HTTPRangeReader } from 'unzipit'; // Configure once at app startup setOptions({ workerURL: new URL('/workers/unzipit-worker.module.js', import.meta.url).href, numWorkers: navigator.hardwareConcurrency || 2 }); async function loadAndExtract(url) { try { // Use HTTPRangeReader for efficient streaming const reader = new HTTPRangeReader(url); const { zip, entries } = await unzip(reader); console.log(`Archive comment: ${zip.comment}`); // Process entries for (const [name, entry] of Object.entries(entries)) { if (name.endsWith('.json')) { const data = await entry.json(); console.log(`${name}:`, data); } } } catch (e) { console.error('Failed to load archive:', e.message); } } ``` -------------------------------- ### Node.js Setup with Workers and Cleanup Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md This example shows a complete setup for Node.js environments. It configures workers using a resolved file path and includes a crucial step to clean up workers after extraction to prevent resource leaks. ```javascript import { unzip, setOptions, cleanup } from 'unzipit'; import { fileURLToPath } from 'url'; import { dirname, resolve } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); // Configure workers for parallel decompression setOptions({ workerURL: resolve(__dirname, '../node_modules/unzipit/dist/unzipit-worker.js'), numWorkers: 4 }); async function extractZip(filename) { try { const { entries } = await unzip(filename); for (const [name, entry] of Object.entries(entries)) { const data = await entry.arrayBuffer(); console.log(`Extracted: ${name} (${data.byteLength} bytes)`); } } finally { // Clean up workers await cleanup(); } } await extractZip('./archive.zip'); ``` -------------------------------- ### Install unzipit Source: https://github.com/greggman/unzipit/blob/main/_autodocs/INDEX.md Install the unzipit library using npm. ```bash npm install unzipit ``` -------------------------------- ### CustomReader Implementation Example Source: https://github.com/greggman/unzipit/blob/main/_autodocs/05-types.md An example implementation of the `Reader` interface for a custom data source. This demonstrates how to provide ZIP data from a non-standard location. ```javascript class CustomReader { async getLength() { return 1024; } async read(offset, size) { // ... fetch bytes from custom source ... return new Uint8Array(bytes); } } const { entries } = await unzip(new CustomReader()); ``` -------------------------------- ### Usage Example: isNode Source: https://github.com/greggman/unzipit/blob/main/_autodocs/10-utility-functions.md Example demonstrating conditional logic based on whether the code is running in Node.js or a browser environment. ```javascript if (isNode) { // Use node:worker_threads import('node:worker_threads').then(...); } else { // Use Web Workers const worker = new Worker(url); } ``` -------------------------------- ### Import Chai and Setup Mocha Source: https://github.com/greggman/unzipit/blob/main/test/index.html Imports the chai assertion library and configures mocha for testing. ```javascript import * as chai from './chai.js'; window.chai = chai; /* global mocha */ mocha.setup('bdd'); mocha.fullTrace(); mocha.timeout(10000); ``` -------------------------------- ### Usage Example Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Demonstrates how to use the HTTPRangeReader with the unzip function to read specific entries from a ZIP file hosted on a server. ```APIDOC ## Usage Example ```javascript import { unzip, HTTPRangeReader } from 'unzipit'; // Stream/download only what's needed using HTTP range requests async function readZipFromServer(url) { const reader = new HTTPRangeReader(url); const { entries } = await unzip(reader); // Only the central directory and accessed entry data are downloaded for (const name of Object.keys(entries).slice(0, 3)) { const data = await entries[name].arrayBuffer(); } } // Without HTTPRangeReader, the entire ZIP would be downloaded via fetch() ``` ``` -------------------------------- ### Parallel File Reading with Unzipit Source: https://github.com/greggman/unzipit/blob/main/README.md Read multiple files from a zip archive in parallel using unzipit. This example demonstrates how to extract all entries, get their names and blobs, and then process them concurrently. ```javascript import {unzip, setOptions} from 'unzipit'; setOptions({workerURL: 'path/to/unzipit-worker.module.js'}); async function readFiles(url) { const {entries} = await unzipit.unzip(url); const names = Object.keys(entries); const blobs = await Promise.all(Object.values(entries).map(e => e.blob())); // names and blobs are now parallel arrays so do whatever you want. const blobsByName = Object.fromEntries(names.map((name, i) => [name, blobs[i]])); } ``` -------------------------------- ### Inflate Raw Async Usage Example Source: https://github.com/greggman/unzipit/blob/main/_autodocs/08-inflation-workers.md Demonstrates how to use `inflateRawAsync` to decompress data into an ArrayBuffer or a Blob with a specified MIME type. Ensure the 'unzipit' library is imported. ```javascript import { inflateRawAsync } from 'unzipit'; // Get decompressed data as ArrayBuffer const compressed = new Uint8Array([...]); const decompressed = await inflateRawAsync(compressed, 1024); // Get decompressed data as Blob with MIME type const blob = await inflateRawAsync(compressed, 1024, 'image/png'); const url = URL.createObjectURL(blob); ``` -------------------------------- ### Unzip Usage with ArrayBufferReader Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Demonstrates how to use the unzip function with an ArrayBufferReader, including Node.js file reading and explicit reader instantiation. Also shows an example with SharedArrayBuffer. ```javascript import { unzip } from 'unzipit'; import ArrayBufferReader from 'unzipit/dist/ArrayBufferReader.module.js'; // Node.js example: Read a ZIP file from disk const fs = require('fs').promises; const buffer = await fs.readFile('archive.zip'); const { entries } = await unzip(new Uint8Array(buffer)); // Or with ArrayBufferReader explicitly const reader = new ArrayBufferReader(buffer); const { entries } = await unzip(reader); // SharedArrayBuffer example (when available) const sharedBuffer = new SharedArrayBuffer(buffer.byteLength); // ... populate sharedBuffer ... const { entries } = await unzip(sharedBuffer); ``` -------------------------------- ### Usage Example: isTypedArraySameAsArrayBuffer Source: https://github.com/greggman/unzipit/blob/main/_autodocs/10-utility-functions.md Example demonstrating how to use isTypedArraySameAsArrayBuffer to conditionally return an ArrayBuffer directly or a copy. ```javascript const buffer = await readAs(reader, fileDataStart, rawEntry.compressedSize); if (isTypedArraySameAsArrayBuffer(buffer)) { // Return the ArrayBuffer directly (no copy needed) return buffer.buffer; } else { // Make a copy return buffer.slice().buffer; } ``` -------------------------------- ### Set Unzipit Options Source: https://github.com/greggman/unzipit/blob/main/_autodocs/05-types.md Example of how to configure Unzipit with worker threads, specifying the worker script path and the number of workers. ```javascript setOptions({ workerURL: '/path/to/unzipit-worker.module.js', numWorkers: 4, useWorkers: true }); ``` -------------------------------- ### Browser: Service Worker Configuration Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md Configure the library to run in a Service Worker context by setting the `workerURL`. This example demonstrates receiving a zip URL via message and posting back the entries. ```javascript // In a Service Worker import { unzip, setOptions } from 'unzipit'; setOptions({ workerURL: '/path/to/unzipit-worker.module.js' // Actually creates nested workers (worker in a worker) }); self.addEventListener('message', async (e) => { const { entries } = await unzip(e.data.zipUrl); self.postMessage({ entries }); }); ``` -------------------------------- ### Loading Specific Image Entry as Blob Source: https://github.com/greggman/unzipit/blob/main/README.md This example shows how to efficiently load a specific image file from a zip archive as a Blob. The browser manages the Blob's memory, and only the necessary parts of the zip file are accessed, making it memory-efficient. ```javascript const {entries} = await unzip(url); const blob = await entries['/some/image.jpg'].blob('image/jpeg'); const url = URL.createObjectURL(blob); const img = new Image(); img.src = url; ``` -------------------------------- ### Handle Compressed Size Mismatch for Stored Files Source: https://github.com/greggman/unzipit/blob/main/_autodocs/06-errors.md This error condition is described but no specific code example is provided in the source text. It relates to mismatches in compressed size for files using compression method 0 (stored). -------------------------------- ### Mocha Test Setup and Script Loading Source: https://github.com/greggman/unzipit/blob/main/test/ts/ts-test.html Configures Mocha for testing and dynamically loads the TypeScript test file. Allows overriding Mocha's timeout via URL query parameters. ```javascript window.testsPromiseInfo = makePromise(); import * as chai from '../chai.js'; window.chai = chai; /* global mocha */ mocha.setup('bdd'); mocha.fullTrace(); mocha.timeout(10000); const query = Object.fromEntries(new URLSearchParams(window.location.search).entries()); if (query.timeout !== undefined) { mocha.timeout(query.timeout); } const script = document.createElement('script'); script.type = 'module'; script.src = 'ts-test.js'; document.head.appendChild(script); ``` -------------------------------- ### Usage Example: Reading ZIP from Server with HTTPRangeReader Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Demonstrates how to use HTTPRangeReader to stream and download only necessary parts of a ZIP file from a URL. This avoids downloading the entire archive. ```javascript import { unzip, HTTPRangeReader } from 'unzipit'; // Stream/download only what's needed using HTTP range requests async function readZipFromServer(url) { const reader = new HTTPRangeReader(url); const { entries } = await unzip(reader); // Only the central directory and accessed entry data are downloaded for (const name of Object.keys(entries).slice(0, 3)) { const data = await entries[name].arrayBuffer(); } } // Without HTTPRangeReader, the entire ZIP would be downloaded via fetch() ``` -------------------------------- ### Memory-Constrained Reader with Streaming (Conceptual) Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md A conceptual example of a memory-constrained reader using streams. Note that pure streaming without knowing the total size is not directly supported by the ZIP format due to the need to read the central directory at the end. For streaming, consider using an HTTPRangeReader or providing the size upfront. ```javascript import { unzip } from 'unzipit'; class StreamingReader { constructor(readStream) { this.readStream = readStream; this.buffer = Buffer.alloc(0); this.length = null; } async getLength() { if (this.length === null) { // For streaming, we need to know the length // This example assumes we know it beforehand throw new Error('Length must be provided for streaming reader'); } return this.length; } async read(offset, length) { // In a real streaming reader, you'd manage buffering // This is a simplified example throw new Error('Streaming reader not fully implemented'); } } // Note: Pure streaming (without knowing total size) won't work // because ZIP format requires reading the central directory at the end. // Use HTTPRangeReader or provide the size upfront. ``` -------------------------------- ### Create Image Gallery from ZIP Archive Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md This client-side JavaScript example demonstrates how to create an image gallery from image files (JPG, PNG, etc.) stored within a ZIP archive. It utilizes web workers for performance and dynamically creates image elements in the DOM. Ensure the `workerURL` is correctly configured for your environment. ```javascript import { unzip, setOptions } from 'unzipit'; // Enable workers for faster parallel loading setOptions({ workerURL: '/path/to/unzipit-worker.module.js', numWorkers: 4 }); async function createGallery(zipUrl) { const { entries } = await unzip(zipUrl); const imageExtensions = ['.jpg', '.jpeg', '.png', '.webp', '.gif']; const gallery = document.createElement('div'); gallery.style.display = 'grid'; gallery.style.gridTemplateColumns = 'repeat(auto-fit, minmax(200px, 1fr))'; gallery.style.gap = '10px'; // Load images in parallel const imagePromises = Object.entries(entries) .filter(([name]) => imageExtensions.some(ext => name.toLowerCase().endsWith(ext))) .map(async ([name, entry]) => { const mimeType = getMimeType(name); const blob = await entry.blob(mimeType); const url = URL.createObjectURL(blob); const img = document.createElement('img'); img.src = url; img.alt = name; img.style.maxWidth = '100%'; const container = document.createElement('div'); container.style.position = 'relative'; container.appendChild(img); const label = document.createElement('div'); label.textContent = name; label.style.position = 'absolute'; label.style.bottom = '0'; label.style.background = 'rgba(0,0,0,0.7)'; label.style.color = 'white'; label.style.width = '100%'; label.style.padding = '5px'; container.appendChild(label); return container; }); const images = await Promise.all(imagePromises); images.forEach(img => gallery.appendChild(img)); document.body.appendChild(gallery); } function getMimeType(filename) { const ext = filename.toLowerCase().split('.').pop(); const mimeTypes = { 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg', 'png': 'image/png', 'webp': 'image/webp', 'gif': 'image/gif', }; return mimeTypes[ext] || 'image/octet-stream'; } await createGallery('https://example.com/photos.zip'); ``` -------------------------------- ### Set File Attributes on Unix-like Systems Source: https://github.com/greggman/unzipit/blob/main/README.md When writing files on macOS or Linux, you can attempt to set file permissions based on the zip entry's metadata. This example extracts and modifies permission bits from `externalFileAttributes`. ```javascript fs.writeFileSync(filename, data); if (process.platform === 'darwin' || process.platform === 'linux') { const platform = entry.versionMadeBy >> 8; const unix = 3; const darwin = 13 if (entry.versionMadeBy === unix || entry.versionMadeBy === darwin) { // no idea what's best here // +- owner read // |+- owner write // ||+- owner execute // |||+- group read // ||||+- group write // |||||+- group execute // ||||||+- other read // |||||||+- other write // ||||||||+- other execute // ||||||||| // VVVVVVVVV let mod = (entry.externalFileAttributes >> 16) & 0b111111111; // all the bits mod &= 0b111100100; // remove write and executable from group and other? mod |= 0b110100100; // add in owner R/W, group R, other R fs.chmodSync(filename, mod); } } ``` -------------------------------- ### Configure Number of Workers for CPU-Bound Workloads Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md For CPU-bound tasks like large decompression, use 1-4 workers per CPU core. This example sets the number of workers to a maximum of 4, based on available hardware concurrency. ```javascript // For CPU-bound workloads (large decompression) // Use 1-4 workers per CPU core const numCores = navigator.hardwareConcurrency || 4; setOptions({ numWorkers: Math.min(4, numCores) }); ``` -------------------------------- ### Parse Structured Data (JSON, CSV) from ZIP Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md This example shows how to parse JSON configuration files and extract headers from CSV files within a ZIP archive. It includes error handling for JSON parsing. This is useful for analyzing archives containing structured data. ```javascript import { unzip } from 'unzipit'; async function analyzeArchive(zipPath) { const { entries } = await unzip(zipPath); // Find and parse all JSON files const configs = {}; for (const [name, entry] of Object.entries(entries)) { if (name.endsWith('.json')) { try { const data = await entry.json(); configs[name] = data; } catch (e) { console.error(`Failed to parse ${name}:`, e.message); } } } // Find and read CSV headers const csvHeaders = {}; for (const [name, entry] of Object.entries(entries)) { if (name.endsWith('.csv')) { const text = await entry.text(); const lines = text.split('\n'); csvHeaders[name] = lines[0].split(','); } } return { configs, csvHeaders }; } const analysis = await analyzeArchive('./data.zip'); console.log('Configs:', analysis.configs); console.log('CSV headers:', analysis.csvHeaders); ``` -------------------------------- ### Unzip Archive and Access Comment Source: https://github.com/greggman/unzipit/blob/main/_autodocs/03-api-reference-zip-class.md Demonstrates how to unzip an archive and access its UTF-8 decoded comment. Includes an example of manual decoding for non-UTF-8 comments. ```javascript import { unzip } from 'unzipit'; const { zip, entries } = await unzip('archive.zip'); console.log('Archive comment:', zip.comment); // If the comment might not be UTF-8, decode manually if (zip.commentBytes.length > 0) { const decoder = new TextDecoder('big5'); // Or other encoding const decodedComment = decoder.decode(zip.commentBytes); console.log('Decoded comment:', decodedComment); } ``` -------------------------------- ### Wrap Unzip Calls with Try-Catch Source: https://github.com/greggman/unzipit/blob/main/_autodocs/06-errors.md Always wrap calls to `unzip()` in a try-catch block to handle potential errors during archive processing. This example demonstrates how to differentiate between invalid ZIP files, encrypted archives, and other unexpected errors. ```javascript async function loadArchive(source) { try { const { entries } = await unzip(source); return entries; } catch (e) { if (e.message.includes('not zip file')) { console.error('Invalid ZIP file'); } else if (e.message.includes('encrypted')) { console.error('Encrypted ZIPs not supported'); } else { console.error('Unexpected error:', e.message); } return null; } } ``` -------------------------------- ### Collecting Archive Metadata Source: https://github.com/greggman/unzipit/blob/main/_autodocs/03-api-reference-zip-class.md An example function that collects various metadata about a ZIP archive, including its comment. ```APIDOC ## Collecting Archive Metadata ### Description This function retrieves and aggregates metadata from a ZIP archive, including the comment, file count, sizes, and date ranges. ### Usage ```javascript async function getArchiveInfo(zipUrl) { const { zip, entries } = await unzip(zipUrl); const info = { comment: zip.comment, fileCount: Object.keys(entries).length, totalSize: Object.values(entries).reduce((sum, e) => sum + e.size, 0), compressed: Object.values(entries).reduce((sum, e) => sum + e.compressedSize, 0), oldestFile: Math.min(...Object.values(entries).map(e => e.lastModDate.getTime())), newestFile: Math.max(...Object.values(entries).map(e => e.lastModDate.getTime())), }; return info; } ``` ``` -------------------------------- ### Extract Unix File Permissions Source: https://github.com/greggman/unzipit/blob/main/_autodocs/02-api-reference-zipentry.md Extracts Unix-like file permissions from zip entries created on Unix or Darwin platforms. It checks the platform identifier in `versionMadeBy` and uses `externalFileAttributes` to get the permission bits. ```javascript function getUnixPerms(entry) { const platform = entry.versionMadeBy >> 8; const UNIX = 3; const DARWIN = 13; if (platform === UNIX || platform === DARWIN) { const perms = (entry.externalFileAttributes >> 16) & 0o777; return perms; } return null; } ``` -------------------------------- ### Raw Zip File Decompression with Custom Name Decoding Source: https://github.com/greggman/unzipit/blob/main/README.md Use `unzipRaw` when filenames in the zip archive are not UTF-8 encoded. This example shows how to decode non-UTF-8 filenames (e.g., Big5 Chinese) using a TextDecoder before processing the entries. ```javascript const {zip, entriesArray} = await unzipit.unzipRaw(url); // decode names as big5 (chinese) const decoder = new TextDecoder('big5'); entriesArray.forEach(entry => { entry.name = decoder.decode(entry.nameBytes); }); const entries = Object.fromEntries(entriesArray.map(v => [v.name, v])); ... // same as above beyond this point ``` -------------------------------- ### Configure and Unzip with Unzipit.js Source: https://github.com/greggman/unzipit/blob/main/test/test-min.html Sets up Unzipit with worker options and then unzips a specified archive. It iterates through the entries, displaying any JPG files as images. ```javascript unzipit.setOptions({ workerURL: '../dist/unzipit-worker.min.js', numWorkers: 2, }); (async function() { const {entries} = await unzipit.unzip('data/large.zip'); Object.entries(entries).forEach(async([name, entry]) => { if (name.endsWith('.jpg')) { const blob = await entry.blob(); const img = new Image(); img.src = URL.createObjectURL(blob); document.body.appendChild(img); } }); }()); ``` -------------------------------- ### Usage of ZipInfoRaw Source: https://github.com/greggman/unzipit/blob/main/_autodocs/05-types.md Shows how to use ZipInfoRaw, including decoding non-UTF-8 filenames. This is useful when filenames are not UTF-8. ```javascript const { zip, entries } = await unzipRaw(buffer); const decoder = new TextDecoder('big5'); entries.forEach(e => { e.name = decoder.decode(e.nameBytes); }); ``` -------------------------------- ### ArrayBufferReader.read() Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Reads a specified number of bytes from the buffer starting at a given offset. Returns a view into the buffer, not a copy. ```APIDOC ## read(offset, length) ### Description Returns a Uint8Array view into the buffer at the given offset and length. Modifications to the returned array will affect the original buffer. ### Signature ```typescript async read(offset: number, length: number): Promise> ``` ### Parameters - **offset** (number) - Required - The starting byte offset to read from. - **length** (number) - Required - The number of bytes to read. ### Returns - **Promise>** - A Uint8Array view of the requested data. ``` -------------------------------- ### Read ZIP File from Disk in Node.js Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md Demonstrates how to read a ZIP file directly from the local filesystem using Node.js. It shows two options: reading the entire file into a buffer or using a custom reader pattern for larger files. Ensure the 'fs/promises' module is available. ```javascript import { unzip, setOptions, cleanup } from 'unzipit'; import { readFile } from 'fs/promises'; async function extractLocalZip(filename) { try { // Option 1: Read entire file into buffer const buffer = await readFile(filename); const { entries } = await unzip(new Uint8Array(buffer)); // Option 2: Use HTTPRangeReader pattern with custom reader // (see custom reader example below) for (const [name, entry] of Object.entries(entries)) { const text = await entry.text(); console.log(`File: ${name}`); console.log(`Size: ${entry.size} bytes`); console.log(`Compressed: ${entry.compressedSize} bytes`); } } catch (e) { console.error('Error:', e.message); } } await extractLocalZip('./data.zip'); ``` -------------------------------- ### Reader interface definition Source: https://github.com/greggman/unzipit/blob/main/README.md Defines the `Reader` interface for custom data sources. It requires methods to get the total length and read data from a specified offset. ```typescript interface Reader { async getLength(): number, async read(offset, size): Uint8Array, } ``` -------------------------------- ### Unzip with BlobReader Usage Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Demonstrates how to use BlobReader explicitly with the unzip function. This is an alternative to passing the Blob directly. ```javascript import { unzip } from 'unzipit'; import BlobReader from 'unzipit/dist/BlobReader.module.js'; // User selects a ZIP file const file = document.querySelector('input[type="file"]').files[0]; // Can use directly const { entries } = await unzip(file); // Or explicitly with BlobReader (same result) const reader = new BlobReader(file); const { entries } = await unzip(reader); ``` -------------------------------- ### Extracting Unix Permissions from Version Made By Source: https://github.com/greggman/unzipit/blob/main/_autodocs/09-zip-format-reference.md Demonstrates how to extract Unix/Linux/macOS file permissions from the `versionMadeBy` and `externalFileAttributes` fields in the Central Directory File Header. ```javascript const osVersion = entry.versionMadeBy >> 8; const permBits = entry.externalFileAttributes >> 16; if (osVersion === 3 || osVersion === 13) { // Unix/Linux/macOS permissions are in permBits } ``` -------------------------------- ### Handle Worker Decompression Errors Source: https://github.com/greggman/unzipit/blob/main/_autodocs/06-errors.md Errors during worker decompression are caught, converted to strings, and re-thrown as new Error objects in the main thread. This example shows how to catch and inspect these errors. ```javascript try { const data = await entry.arrayBuffer(); } catch (e) { // e.message might be: "decompressed size exceeds limit: 999 > 500" } ``` -------------------------------- ### Usage of ZipInfo Source: https://github.com/greggman/unzipit/blob/main/_autodocs/05-types.md Demonstrates how to extract ZIP archive metadata and entries using the ZipInfo type. ```javascript const { zip, entries } = await unzip('archive.zip'); const file = entries['path/to/file.txt']; ``` -------------------------------- ### Export Statements Source: https://github.com/greggman/unzipit/blob/main/_autodocs/10-utility-functions.md Main entry point exports for the unzipit library. ```typescript export { ArrayBufferReader, BlobReader }; export * from './HTTPRangeReader.js'; export type { Reader } from './BlobReader.js'; export type { UnzipitOptions } from './inflate.js'; export interface Zip { ... } export interface ZipInfoRaw { ... } export interface ZipInfo { ... } export type TypedArray = ...; export class ZipEntry { ... } export function setOptions(options: UnzipitOptions): void; export async function unzipRaw(source: ...): Promise; export async function unzip(source: ...): Promise; export function cleanup(): void; ``` -------------------------------- ### Basic Unzip Usage Source: https://github.com/greggman/unzipit/blob/main/_autodocs/INDEX.md Demonstrates basic usage of the unzip function to extract entries from a zip archive and log their names and sizes. Requires the 'unzipit' library to be imported. ```javascript import { unzip } from 'unzipit'; const { entries } = await unzip('archive.zip'); for (const [name, entry] of Object.entries(entries)) { console.log(`${name}: ${entry.size} bytes`); } ``` -------------------------------- ### Import unzipit functions Source: https://github.com/greggman/unzipit/blob/main/README.md Import the necessary functions from the unzipit library. These include functions for unzipping, setting options, and cleaning up workers. ```javascript import { unzipit, unzipitRaw, setOptions, cleanup } from 'unzipit'; ``` -------------------------------- ### Reader Interface Definition Source: https://github.com/greggman/unzipit/blob/main/_autodocs/05-types.md Defines the interface for custom ZIP data sources. Implement this to read ZIP files from various sources like databases or memory. Includes methods for getting the total length and reading specific byte ranges. ```typescript interface Reader { getLength(): Promise; read(offset: number, size: number): Promise>; sliceAsBlob?(offset: number, length: number, type?: string): Promise; } ``` -------------------------------- ### Local Script Include Source: https://github.com/greggman/unzipit/blob/main/README.md Include unzipit using a script tag when not using a module bundler. Use the minified version for production to reduce file size. ```html ``` -------------------------------- ### Catching 'invalid central directory file header signature' Error Source: https://github.com/greggman/unzipit/blob/main/_autodocs/06-errors.md This example demonstrates how to catch errors related to an invalid central directory signature, which typically indicates a corrupt ZIP archive. The code checks the error message for the relevant substring. ```javascript try { const { entries } = await unzip(data); } catch (e) { if (e.message.includes('central directory file header signature')) { console.error('Corrupt ZIP archive'); } } ``` -------------------------------- ### unzip and unzipRaw Source: https://github.com/greggman/unzipit/blob/main/README.md Asynchronous functions to unzip files from various sources. `unzip` returns entries as an object mapping filenames to `ZipEntry` objects, while `unzipRaw` returns entries as an array of `ZipEntry` objects. This is useful when filenames are not valid UTF-8. ```APIDOC ## unzip, unzipRaw ### Description Asynchronous functions that take a url, `Blob`, `TypedArray`, `ArrayBuffer`, or a `Reader`. Both functions return an object with fields `zip` and `entries`. - `unzip`: `entries` is an object mapping filenames to `ZipEntry`s. - `unzipRaw`: `entries` is an array of `ZipEntry`s. Use this if filenames are not utf8. ### Method `async` ### Parameters #### Source - `url` (string): The URL of the zip file. - `src` (`Blob` | `TypedArray` | `ArrayBuffer` | `Reader`): The zip file content as a Blob, TypedArray, ArrayBuffer, or a custom Reader. ### Return Value `ZipInfo` or `ZipInfoRaw`: - `zip`: An object containing zip file information. - `entries`: An object (for `unzip`) or array (for `unzipRaw`) of `ZipEntry` objects. ### ZipInfo Type ```typescript type ZipInfo = { zip: Zip, entries: {[key: string]: ZipEntry}, }; ``` ### ZipInfoRaw Type ```typescript type ZipInfoRaw = { zip: Zip, entries: [ZipEntry], }; ``` ### Zip Class ```typescript class Zip { comment: string, commentBytes: Uint8Array, } ``` ### ZipEntry Class ```typescript class ZipEntry { async blob(type?: string): Blob async arrayBuffer(): ArrayBuffer async text(): string async json(): any name: string nameBytes: Uint8Array size: number compressedSize: number comment: string commentBytes: Uint8Array lastModDate: Date isDirectory: bool encrypted: bool externalFileAttributes: number versionMadeBy: number } ``` ### Reader Interface ```typescript interface Reader { async getLength(): number async read(offset, size): Uint8Array } ``` ``` -------------------------------- ### Dynamically Load Test Script Source: https://github.com/greggman/unzipit/blob/main/test/index.html Creates and appends a script tag to load the main test module. ```javascript const script = document.createElement('script'); script.type = 'module'; script.src = 'index.js'; document.head.appendChild(script); ``` -------------------------------- ### HTTPRangeReader Constructor Source: https://github.com/greggman/unzipit/blob/main/_autodocs/04-api-reference-readers.md Initializes an HTTPRangeReader with the URL of a ZIP file. The server must support HTTP Range requests. ```typescript constructor(url: string) ``` -------------------------------- ### text() Source: https://github.com/greggman/unzipit/blob/main/_autodocs/02-api-reference-zipentry.md Extracts the entry's content as a UTF-8 decoded string. This is ideal for reading text-based files like configuration or readme files. ```APIDOC ## text() ### Description Extract entry content as a UTF-8 decoded string. This method is ideal for reading text-based files such as configuration files, READMEs, or source code. ### Method `text(): Promise` ### Return Type `Promise` — Decompressed content decoded as UTF-8 text. ### Throws - Error: If the entry is encrypted. - Error: If an unsupported compression method is used. - Error: If there are invalid UTF-8 sequences (may silently replace invalid bytes). - Error: If there are file data issues. ### Usage Example ```javascript const { entries } = await unzip('archive.zip'); // Read a text file const content = await entries['notes.txt'].text(); console.log(content); // Validate size before reading large files if (entries['huge.txt'].size > 50 * 1024 * 1024) { console.error('File too large'); } else { const text = await entries['huge.txt'].text(); } ``` ### Notes - Always assumes UTF-8 encoding. For other encodings, use `arrayBuffer()` and decode manually. - TextDecoder silently replaces invalid UTF-8 sequences; no error is thrown. ``` -------------------------------- ### Configure unzipit Options with Workers Source: https://github.com/greggman/unzipit/blob/main/_autodocs/01-api-reference-main.md Use `setOptions` to enable worker threads for faster parallel decompression. Setting `workerURL` automatically enables `useWorkers`. Workers are created lazily and are useful for CPU-bound tasks. ```javascript import { unzip, setOptions } from 'unzipit'; // Enable workers for faster parallel decompression setOptions({ workerURL: '/path/to/unzipit-worker.module.js', numWorkers: 4 }); // Now unzip calls will use workers const { entries } = await unzip('archive.zip'); // Read multiple files in parallel const blobs = await Promise.all( Object.values(entries).map(e => e.blob()) ); ``` -------------------------------- ### Basic ZIP Extraction in Browser Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md Demonstrates how to extract a ZIP archive directly from a URL in an HTML page using UnzipIt. Requires the 'unzipit.module.js' import. ```html ``` -------------------------------- ### Unzip Blob or ArrayBuffer with Custom Fetch Options Source: https://github.com/greggman/unzipit/blob/main/README.md When needing to specify CORS, credentials, or other fetch options, first fetch the resource as a Blob or ArrayBuffer, then pass it to unzip. This bypasses the library's direct URL handling for more control. ```javascript import {unzip} from 'unzipit'; ... const req = await fetch(url, { mode: 'cors' }); const blob = await req.blob(); const {entries} = await unzip(blob); ``` -------------------------------- ### Browser: Handling Cross-Origin Worker URLs Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md Demonstrates setting a cross-origin `workerURL`. The library attempts fallbacks like Blob URLs and data URIs to circumvent CORS issues if direct loading fails. ```javascript // This might fail due to CORS setOptions({ workerURL: 'https://different-origin.com/unzipit-worker.js' }); // Library will try: // 1. Direct Worker(url) — might fail due to CORS // 2. fetch(url, {mode: 'cors'}) — needs CORS headers // 3. data URI with base64 — always works ``` -------------------------------- ### Load Zip File as ArrayBuffer in Node.js Source: https://github.com/greggman/unzipit/blob/main/README.md Reads a file into an ArrayBuffer and then uses it to unzip the file. Ensure the file exists before attempting to read. ```javascript const unzipit = require('unzipit'); const fsPromises = require('fs').promises; async function readFiles(filename) { const buf = await fsPromises.readFile(filename); const {zip, entries} = await unzipit.unzip(new Uint8Array(buf)); ... (see code above) } ``` -------------------------------- ### ES Module Import (Browser) Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md Import the unzip function using ES Module syntax for use in modern browsers. ```javascript import { unzip } from 'unzipit'; ``` -------------------------------- ### ZipEntry Methods Source: https://github.com/greggman/unzipit/blob/main/_autodocs/INDEX.md Methods available on each ZipEntry object to extract file content in various formats. ```APIDOC ## ZipEntry Methods ### blob(type?) #### Description Extracts the file content as a Blob. #### Parameters - **type** (string) - Optional - The MIME type of the Blob. #### Returns - Promise ### arrayBuffer() #### Description Extracts the file content as an ArrayBuffer. #### Returns - Promise ### text() #### Description Extracts the file content as a string. #### Returns - Promise ### json() #### Description Extracts the file content and parses it as JSON. #### Returns - Promise ### Request Example ```javascript const blob = await entries['path/to/file.jpg'].blob('image/jpeg'); const text = await entries['readme.txt'].text(); const data = await entries['data.json'].json(); ``` ``` -------------------------------- ### Global Import (Browser, No Bundler) Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md Include unzipit via a script tag for use in browsers without a module bundler. The unzip function is available on the global unzipit object. ```html ``` -------------------------------- ### Browser Worker Loading Fallback Source: https://github.com/greggman/unzipit/blob/main/_autodocs/08-inflation-workers.md Illustrates the fallback chain for loading workers in a browser environment, handling direct instantiation, Fetch+Blob URL, and Data URI methods. ```typescript 1. Direct instantiation: `new Worker(url)` 2. Fetch + Blob URL: Fetch script, create Blob URL, then instantiate 3. Data URI: Base64-encode script into data URI and instantiate 4. Failure: Log warning and fall back to local decompression ``` -------------------------------- ### Set unzipit options Source: https://github.com/greggman/unzipit/blob/main/README.md Configure unzipit behavior using the `setOptions` function. Options include enabling web workers for parallel decompression and specifying the worker script URL. ```typescript setOptions(options: UnzipitOptions) ``` -------------------------------- ### CDN Module Import Source: https://github.com/greggman/unzipit/blob/main/README.md Import unzipit directly from a CDN using a module import. This is useful for quick testing or when you don't want to manage local files. ```javascript import * as unzipit from 'https://unpkg.com/unzipit@2.0.1/dist/unzipit.module.js'; ``` -------------------------------- ### CDN Script Include Source: https://github.com/greggman/unzipit/blob/main/README.md Include unzipit from a CDN using a script tag. This method is suitable for projects that do not use ES modules. ```html ``` -------------------------------- ### json() Source: https://github.com/greggman/unzipit/blob/main/_autodocs/02-api-reference-zipentry.md Extracts the entry's content as a UTF-8 string and parses it as JSON. This is convenient for configuration or data files in JSON format. ```APIDOC ## json() ### Description Extract entry content as UTF-8 text and parse it as JSON. This method is convenient for directly loading configuration or data files that are in JSON format. ### Method `json(): Promise` ### Return Type `Promise` — Result of `JSON.parse()` on the entry's text content. ### Throws - SyntaxError: If the entry contains invalid JSON. - Error: If the entry is encrypted or uses an unsupported compression method. ### Usage Example ```javascript const { entries } = await unzip('config.zip'); const appConfig = await entries['app.config.json'].json(); console.log(appConfig.version, appConfig.apiUrl); // Read multiple JSON files in parallel const results = await Promise.all([ entries['manifest.json'].json(), entries['settings.json'].json(), entries['data.json'].json(), ]); ``` ### Notes - Equivalent to `text().then(t => JSON.parse(t))`. - Throws if the content is not valid JSON. - Does not validate the resulting object structure. ``` -------------------------------- ### Parallel ZIP Decompression with Workers in Node.js Source: https://github.com/greggman/unzipit/blob/main/_autodocs/11-complete-usage-examples.md Shows how to configure and use workers for parallel decompression of ZIP files, improving performance for large archives. It requires setting the 'workerURL' and 'numWorkers' options at startup and cleaning up workers using 'cleanup()' when done. Ensure 'unzipit-worker.js' is accessible. ```javascript import { unzip, setOptions, cleanup } from 'unzipit'; import { readFile } from 'fs/promises'; // Configure workers at startup setOptions({ workerURL: require.resolve('unzipit/dist/unzipit-worker.js'), numWorkers: 4 }); async function extractZipParallel(filename) { try { const buffer = await readFile(filename); const { entries } = await unzip(new Uint8Array(buffer)); // Read all files in parallel const results = await Promise.all( Object.entries(entries).map(async ([name, entry]) => { const data = await entry.arrayBuffer(); return { name, size: data.byteLength }; }) ); console.log('Extracted files:', results); } finally { // Clean up workers before exiting await cleanup(); } } await extractZipParallel('./archive.zip'); ``` -------------------------------- ### setOptions Source: https://github.com/greggman/unzipit/blob/main/_autodocs/01-api-reference-main.md Configures global library behavior, including worker usage for decompression. This function allows you to customize how Unzipit handles decompression tasks, such as enabling parallel processing with worker threads. ```APIDOC ## `setOptions(options)` ### Description Configure global library behavior, including worker usage for decompression. ### Parameters #### Options Object - **options.useWorkers** (boolean) - Optional - Default: `false` - Enable or disable worker threads for decompression. - **options.workerURL** (string) - Optional - Description: Path to the worker script (e.g., `unzipit-worker.module.js`). Setting this automatically enables `useWorkers`. - **options.numWorkers** (number) - Optional - Default: `1` - Number of worker threads to create for parallel decompression. ### Return Type `void` ### Usage Example ```javascript import { unzip, setOptions } from 'unzipit'; // Enable workers for faster parallel decompression setOptions({ workerURL: '/path/to/unzipit-worker.module.js', numWorkers: 4 }); // Now unzip calls will use workers const { entries } = await unzip('archive.zip'); // Read multiple files in parallel const blobs = await Promise.all( Object.values(entries).map(e => e.blob()) ); ``` ### Notes - Setting `workerURL` automatically sets `useWorkers` to true. - Workers are useful for CPU-bound decompression tasks; overhead may not justify use for very small files. - Workers are created lazily — only instantiated when needed. - In Node.js, requires the worker path to be resolved: `require.resolve('unzipit/dist/unzipit-worker.js')` ``` -------------------------------- ### Default Unzipit Configuration (No Workers) Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md Uses the default single-threaded decompression without workers. This is suitable for smaller archives or when main thread blocking is acceptable. ```javascript import { unzip } from 'unzipit'; // Default: single-threaded, no workers const { entries } = await unzip('archive.zip'); ``` -------------------------------- ### Extract Entry as Blob Source: https://github.com/greggman/unzipit/blob/main/_autodocs/02-api-reference-zipentry.md Use the `blob()` method to extract entry content as a Blob. Specify a MIME type for the returned Blob. Useful for media files. ```javascript const { entries } = await unzip('images.zip'); const imageBlob = await entries['photo.jpg'].blob('image/jpeg'); const url = URL.createObjectURL(imageBlob); const img = document.createElement('img'); img.src = url; document.body.appendChild(img); ``` -------------------------------- ### Create Promise Helper Source: https://github.com/greggman/unzipit/blob/main/test/index.html A helper function to create a promise and expose its resolve/reject functions. ```javascript function makePromise() { const info = {}; const promise = new Promise((resolve, reject) => { Object.assign(info, {resolve, reject}); }); info.promise = promise; return info; } window.testsPromiseInfo = makePromise(); ``` -------------------------------- ### Configure Number of Workers for Memory-Constrained Environments Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md In environments with limited memory, it's advisable to use fewer workers to reduce memory consumption. ```javascript // For memory-constrained environments // Use fewer workers setOptions({ numWorkers: 1 }); ``` -------------------------------- ### Configure Number of Workers for I/O-Bound Workloads Source: https://github.com/greggman/unzipit/blob/main/_autodocs/07-configuration.md For I/O-bound tasks such as streaming downloads, increasing the number of workers can improve performance by allowing more concurrent waiting on network responses. ```javascript // For I/O-bound workloads (streaming downloads) // More workers can help if each is waiting on network setOptions({ numWorkers: 8 }); ``` -------------------------------- ### Process Mixed Content Types in a Zip Archive Source: https://github.com/greggman/unzipit/blob/main/_autodocs/02-api-reference-zipentry.md Demonstrates how to read and process various file types (JSON, images, text) from a zip archive using the unzipit library. Ensure the zip URL is accessible and the archive contains the expected files. ```javascript import { unzip } from 'unzipit'; async function processArchive(zipUrl) { const { zip, entries } = await unzip(zipUrl); console.log('Archive comment:', zip.comment); // Read manifest const manifest = await entries['manifest.json'].json(); // Display images for (const name of Object.keys(entries)) { if (name.endsWith('.png')) { const blob = await entries[name].blob('image/png'); const url = URL.createObjectURL(blob); const img = document.createElement('img'); img.src = url; document.body.appendChild(img); } } // Read text files if (entries['README.md']) { const readme = await entries['README.md'].text(); console.log(readme); } } ``` -------------------------------- ### URL Encode Regular Expression for Testing Source: https://github.com/greggman/unzipit/blob/main/README.md Demonstrates how to URL-encode a regular expression for use in the test runner's grep parameter. This is necessary to ensure special characters in the regex are correctly interpreted by the URL. ```javascript encodeURIComponent('j(.*?)son') ``` ```plaintext "j(.*%3F)son" ``` -------------------------------- ### Stateless File Reader for Unzipping in Node.js Source: https://github.com/greggman/unzipit/blob/main/README.md Implements a stateless file reader that opens and closes the file for each read operation. This is suitable when minimal resource holding is desired, but may incur overhead for frequent access. ```javascript const unzipit = require('unzipit'); const fsPromises = require('fs').promises; class StatelessFileReader { constructor(filename) { this.filename = filename; } async getLength() { if (this.length === undefined) { const stat = await fsPromises.stat(this.filename); this.length = stat.size; } return this.length; } async read(offset, length) { const fh = await fsPromises.open(this.filename); const data = new Uint8Array(length); await fh.read(data, 0, length, offset); await fh.close(); return data; } } async function readFiles(filename) { const reader = new StatelessFileReader(filename); const {zip, entries} = await unzipit.unzip(reader); ... (see code above) } ```