react-native-zip-archive
Native zip and unzip for React Native and Expo — password-protected archives, selective extraction, and cancellable operations on iOS and Android.
Repository Health
Technical Analysis
react-native-zip-archive is a native module that gives React Native and Expo apps real zip and unzip capabilities on both iOS and Android, backed by native compression libraries rather than a pure-JavaScript implementation. It supports the New Architecture via TurboModules with a fallback path to the legacy NativeModules bridge, so the same JS API works whether or not the New Architecture is enabled, as long as the app is rebuilt against RN >= 0.70.
Beyond basic zip/unzip, the library handles password-protected archives with configurable encryption (ZipCrypto/AES-128/AES-256), selective extraction of specific entries or directories, listing archive contents without extracting, unzipping bundled app assets, and reporting progress through an event emitter. Long-running operations can be cancelled via a shared cancel() call or the standard AbortSignal pattern, and both platforms serialize zip/unzip work through a single queue to avoid concurrent native operations.
What You Get
- Native zip/unzip on iOS and Android instead of a pure-JS implementation, avoiding the memory overhead of libraries like JSZip for large files.
- Password-protected archive support with STANDARD (ZipCrypto), AES-128, and AES-256 encryption methods.
- Selective extraction and listing — pull specific files or directories out of an archive, or list contents (path, size, compressed size, encryption flag) without extracting anything.
- AbortSignal and cancel() support for stopping in-flight zip/unzip operations, plus a progress event emitter via subscribe().
- TurboModule (New Architecture) support with automatic fallback to the legacy NativeModules bridge, plus an Expo config plugin for development builds/EAS.
Common Use Cases
- Unpacking downloaded content bundles (assets, themes, offline data packs) into the app’s document directory after fetching them from a server.
- Extracting bundled app assets shipped inside the APK or app bundle via unzipAssets, without needing an absolute filesystem path.
- Building password-protected export/import flows, e.g. encrypting a user’s exported data before sharing it outside the app.
- Previewing archive contents (file list, sizes) before committing to a full extraction, useful for large downloaded zip files.
Under The Hood
Architecture The JS layer (index.js) is a thin, functional wrapper: lazy-resolves the native module through TurboModuleRegistry with a NativeModules fallback (getRNZipArchive()), normalizes arguments across multiple overloaded call shapes (positional args vs options object) via small resolver functions (resolveZipOptions, resolvePasswordOptions, resolveUnzipArgs), and layers an AbortSignal wrapper (withAbort) around each native call using Promise.race against an abort gate. On Android, RNZipArchiveModule.java is a single large module class backed by zip4j, delegating path-safety concerns to ZipSecurity.java (a small, focused utility that disables symlink extraction and canonical-path-validates every entry to block Zip Slip) and StreamUtil.java for I/O helpers; codegen specs (specs/NativeZipArchive.ts, android/src/paper) generate the TurboModule interface consumed by both the old and new architecture code paths. iOS mirrors this via RNZipArchive.mm/h with RCT_EXPORT_MODULE and a conditionally compiled TurboModule getter. Because RNZipArchiveModule.java is the single choke point for both zip and unzip logic on Android, swapping the core native dependency would require re-verifying path validation, error codes, and progress events together.
Tech Stack package.json declares peer dependencies on react and react-native, with Jest for testing and a React Native community ESLint config for linting. Android build uses zip4j for the actual compression/encryption implementation, wired through Gradle with separate main and paper source sets to isolate New/old-architecture codegen output; codegen is driven by a codegenConfig block in package.json pointing at the TypeScript native spec. CI runs dedicated Android build, iOS build, old-architecture, end-to-end (Maestro), and zip-interoperability workflows, plus a separate publish workflow — a notably thorough matrix for a small utility library. Two full playground apps for plain React Native and Expo are checked into the repo as living smoke-test harnesses for development builds.
Code Quality The repo has real automated tests on both the JS and native side: multiple Jest test files cover the public API, module integration, package metadata, the Expo config plugin, and zip interoperability, and the Android module has JUnit tests for its security utility, error codes, entry-selection matching, and array conversion helpers — including a dedicated test validating the Zip Slip path-traversal fix. Errors are modeled explicitly through a ZipError factory with a fixed error-code enum rather than raw strings, and the JS layer consistently rejects with typed errors instead of swallowing failures. TypeScript types are hand-maintained as function overloads for every call shape rather than generated. ESLint is configured and CI enforces multiple build/test workflows before publish, with no signs of neglected lint or test failures in the sampled files.
API Design The public API is small and consistent — one verb-based function per operation (zip, unzip, zipWithPassword, unzipWithPassword, listContents, unzipAssets, getUncompressedSize, cancel, subscribe) with named constants for compression levels and encryption methods instead of magic numbers or strings. Backward compatibility is handled carefully: several functions accept either legacy positional arguments or a single options object, auto-detected at runtime, so adding AbortSignal support did not break existing call sites. Getting started requires one install plus an Expo config-plugin entry for Expo users, with no separate native-linking step documented for supported React Native versions. The README documents an explicit version-compatibility matrix and a comparison table against alternative approaches, which is unusually candid, developer-facing documentation for a small library.
Used by 3 apps in this directory
Joplin
Note Taking
The privacy-first, open-source note-taking app with end-to-end encrypted sync, AI assistance, and a powerful plugin ecosystem across every platform.
MentraOS
Developer Tools · AI Development
The open source operating system and SDK that lets developers build one app and run it across smart glasses from Even Realities, Vuzix, Mentra Live, and more.
Notesnook
Note Taking · File Storage · Security
End-to-end encrypted, open-source note-taking where your data stays yours — even from the server.