| name | zip-memory-operations |
| description | In-memory ZIP read/write operations without temp files. adm-zip patterns for extracting, modifying, and inspecting ZIP archives entirely in RAM — ideal for release package verification. Sources: cthackers/adm-zip. |
/zip-memory-operations
When to Use
- Inspect yamtam release ZIP contents without extracting to disk
- Patch a single file inside a ZIP (update MANIFEST.json in release archive)
- Verify release archive integrity and file list before publishing
- Extract specific files from ZIP into memory buffers for validation
Do NOT use for
- Large archives (> 500MB in memory) — use streaming [[archive-stream-patterns]]
- Creating new archives from scratch (use node-archiver for streaming creation)
Inspect archive
import AdmZip from 'adm-zip'
function inspectRelease(zipPath: string): void {
const zip = new AdmZip(zipPath)
const entries = zip.getEntries()
console.log(`[zip] ${entries.length} entries in ${zipPath}`)
entries.forEach(e => {
console.log(` ${e.entryName.padEnd(60)} ${e.header.size.toLocaleString()} bytes`)
})
}
Extract single file to memory
function readFromZip(zipPath: string, entryName: string): string {
const zip = new AdmZip(zipPath)
const entry = zip.getEntry(entryName)
if (!entry) throw new Error(`[zip] entry not found: ${entryName}`)
return zip.readAsText(entry)
}
const manifest = JSON.parse(
readFromZip('/tmp/yamtam-1.3.48.zip', 'yamtam-1.3.48/MANIFEST.json')
)
console.log('Release version:', manifest.version)
Patch file inside ZIP (in-memory)
function patchZipEntry(
zipPath: string,
entryName: string,
content: string,
outputPath?: string
): void {
const zip = new AdmZip(zipPath)
zip.updateFile(entryName, Buffer.from(content, 'utf8'))
zip.writeZip(outputPath ?? zipPath)
}
patchZipEntry(
'/tmp/yamtam-1.3.48.zip',
'yamtam-1.3.48/MANIFEST.json',
JSON.stringify({ ...manifest, manifest_updated: new Date().toISOString() }, null, 2)
)
Verify file checksums in archive
import { createHash } from 'crypto'
function verifyZipContents(
zipPath: string,
expected: Record<string, string>
): { ok: boolean; failures: string[] } {
const zip = new AdmZip(zipPath)
const failures: string[] = []
for (const [entry, expectedHash] of Object.entries(expected)) {
const data = zip.readFile(entry)
if (!data) { failures.push(`${entry}: MISSING`); continue }
const actual = createHash('sha256').update(data).digest('hex')
if (actual !== expectedHash) failures.push(`${entry}: hash mismatch`)
}
return { ok: failures.length === 0, failures }
}
Anti-Fake-Pass Checklist
❌ new AdmZip() on 1GB file → loads entire archive into RAM → OOM
❌ zip.getEntry() returns null for wrong path separator (/ vs \) → use / consistently
❌ zip.readFile() returns null not empty buffer → null check required
❌ writeZip() overwrites source while reading from it → use separate output path
❌ No CRC verification on extraction → corrupted entries silently extracted
❌ Password-protected ZIPs — adm-zip supports basic encryption but not AES-256