Pure TypeScript implementation of StormLib for reading MPQ (Mo'PaQ) archives. No native bindings, no WASM — just TypeScript.
MPQ is the archive format used by Blizzard Entertainment games including Diablo, StarCraft, Warcraft III, and World of Warcraft.
- Read-only MPQ archive support
- MPQ V1 through V4 format support
- Pure TypeScript — no native addons or WASM compilation required
- Synchronous API — simple, straightforward file extraction
- Single runtime dependency — only pako for zlib
- Dual module output — ships both CommonJS and ESM builds with full type declarations
| Algorithm | Status |
|---|---|
| zlib (Deflate) | Supported |
| PKWARE DCL (Implode) | Supported |
| Blizzard Huffman | Supported |
| ADPCM Mono / Stereo | Supported |
| Sparse (RLE) | Supported |
| BZIP2 | Not supported |
| LZMA | Not supported |
BZIP2 and LZMA are rarely used in practice (only some SC2/HotS archives). If you need them, contributions are welcome.
| Table | Status |
|---|---|
| Classic Hash Table | Supported |
| Classic Block Table | Supported |
| Hi-Block Table (V2+) | Supported |
| HET Table (V3+) | Supported |
| BET Table (V3+) | Supported |
npm install stormlib-jsimport { MpqArchive } from 'stormlib-js';
// Open an archive
const archive = MpqArchive.open('game.mpq');
// List known files (from internal listfile)
const files = archive.getFileList();
console.log(files);
// Extract a file
const data = archive.extractFile('war3map.j');
console.log(data.toString('utf-8'));
// Search with wildcards
const results = archive.findFiles('*.blp');
for (const entry of results) {
console.log(entry.fileName, entry.fileSize);
}
// Clean up
archive.close();The main class for working with MPQ archives.
Opens an MPQ archive from a file path.
const archive = MpqArchive.open('archive.mpq');
// With options
const archive = MpqArchive.open('archive.mpq', {
noListfile: false, // Skip loading internal (listfile)
noAttributes: false, // Skip loading internal (attributes)
noHeaderSearch: false, // Don't search for MPQ header (assume offset 0)
forceMpqV1: false, // Force reading as MPQ V1
});Returns true if the file exists in the archive.
if (archive.hasFile('war3map.j')) {
// ...
}Extracts a file and returns its contents as a Buffer.
const buf = archive.extractFile('war3map.w3i');Opens a file handle for more control over reading.
const file = archive.openFile('units.doo');
console.log(file.size, file.compressedSize, file.flags);
const data = file.read();
file.close();Returns an array of known file names (populated from the internal listfile).
const names = archive.getFileList();
// ['war3map.j', 'war3map.w3e', ...]Searches for files matching a wildcard pattern. Supports * and ?.
const textures = archive.findFiles('*.blp');
for (const f of textures) {
console.log(f.fileName, f.fileSize, f.compSize);
}Lists all file entries including unnamed ones. Unnamed entries are given synthetic names like File00000001.xxx.
const all = archive.enumerateFiles();
console.log(`Total: ${all.length} files`);Applies an external list of file names to resolve unnamed entries. Useful for archives without an internal (listfile).
const resolved = archive.addListfile([
'war3map.j', 'war3map.w3e', 'war3map.w3i',
]);
console.log(`${resolved} new names resolved`);Returns the parsed MPQ header.
const header = archive.getHeader();
console.log(`Format: V${header.wFormatVersion + 1}`);
console.log(`Sector size: ${512 << header.wSectorSize}`);Closes the archive and releases the underlying file handle.
All errors extend MpqError:
| Class | Description |
|---|---|
MpqNotFoundError |
File not found in the archive |
MpqCorruptError |
Archive data is corrupt |
MpqUnsupportedError |
Unsupported feature (e.g. BZIP2) |
MpqEncryptionError |
Decryption failure |
MpqCompressionError |
Decompression failure |
import { MpqNotFoundError } from 'stormlib-js';
try {
archive.extractFile('nonexistent.txt');
} catch (err) {
if (err instanceof MpqNotFoundError) {
console.log('File does not exist');
}
}This library can read MPQ archives from:
- Diablo / Diablo II (V1, Huffman/PKWARE compression)
- StarCraft / Brood War (V1, Huffman/PKWARE compression)
- Warcraft III / The Frozen Throne (V1, zlib compression)
- World of Warcraft (V2, 64-bit offsets)
- StarCraft II (V3/V4, HET/BET tables)
Low-level crypto and hashing functions are exported for specialized use cases:
import {
hashString, jenkinsHash,
decryptBlock, encryptBlock,
getStormBuffer,
MPQ_HASH_TABLE_INDEX,
MPQ_HASH_NAME_A,
} from 'stormlib-js';
// Compute MPQ hash
const idx = hashString('(listfile)', MPQ_HASH_TABLE_INDEX);
// Jenkins hash for HET tables
const hash = jenkinsHash('war3map.j');# Install dependencies
npm install
# Run tests
npm test
# Type check
npm run typecheck
# Build
npm run build- Ladislav Zezula for the original StormLib C/C++ library and the comprehensive MPQ format documentation
- The StormLib documentation for format specifications
MIT