Releases: Preeternal/react-native-file-hash
v2.0.5 - Zig C ABI v3, streaming files, and cancellation
This release updates the Zig core to zig-files-hash v0.0.5, moves file
hashing fully onto streaming paths, and adds AbortController-style cancellation
for both the native and zig engines.
Existing positional JavaScript calls still work, but the new object-style
request API is now the recommended API shape because it can carry
algorithm, hashOptions, and signal without placeholder arguments.
Why cancellation matters
Hashing a large video, archive, or offline map can take long enough for the
user to change their mind. With AbortController, apps can stop native hashing
when the user leaves the screen, picks another file, closes a modal, retries an
upload, or cancels a verification step.
That means less wasted CPU and battery, fewer stale promises updating old UI
state, and a cleaner integration with the same cancellation pattern developers
already use for fetch.
Added
- Added object-style request overloads for both public hash functions:
fileHash(filePath, { algorithm, hashOptions, signal })stringHash(text, { algorithm, encoding, hashOptions, signal })
- Added
HashRequest,StringHashRequest,HashAbortSignal, and
HashAbortErrorTypeScript types. - Added optional
AbortSignalsupport for cancelling work the app no longer
needs. Aborting rejects withE_CANCELLEDand normalizes the JS error name
toAbortError. - Added native
cancelOperation(operationId)plumbing behind the JS API.
Operation ids are internal; users should cancel withAbortController. - Added cancellation coverage for file hashing and string hashing in both
engines:- Android native engine checks cancellation between stream chunks and closes
the activeInputStreamon cancel. - Android Zig engine forwards cancellation into the Zig operation state.
- iOS native engine tracks
Operationinstances and rejects cancelled work
withE_CANCELLED. - iOS Zig engine tracks operations and forwards cancellation into the Zig
operation state.
- Android native engine checks cancellation between stream chunks and closes
- Added benchmark controls to the example app, including generated local test
files, warmups, samples, per-algorithm results, and cancellation.
Changed
- File hashing now uses streaming implementations throughout the runtime.
The Zig file path no longer depends on the old one-shot file API:- Android Zig reads React Native file/content URIs through an
InputStream
and feedszfh_hasher_*. - iOS Zig streams file URLs/paths through
zfh_hasher_*. - Native engines continue to stream file data from disk.
- Android Zig reads React Native file/content URIs through an
- Updated the bundled Zig core to
zig-files-hashv0.0.5. - Updated the Zig integration to C ABI v3 (
ZFH_API_VERSION = 3) and the new
request/operation-state API. - Updated Zig error mapping for the v3 ABI, including
ZFH_OUTPUT_BUFFER_TOO_SMALL,ZFH_OPERATION_CANCELED, and
ZFH_INVALID_STATE. fileHash(path)andfileHash(path, {})both default toSHA-256.stringHash(text)andstringHash(text, {})both default toSHA-256with
utf8input encoding.- The example app now uses the fresh object-style API and exposes cancel
buttons for file hashing, string hashing, and benchmark runs. scripts/check-packed-prebuilts.shnow uses an isolated npm cache while
packing and verifies the generated Zig C ABI header in the package.
Deprecated
- Deprecated positional overloads:
fileHash(filePath, algorithm, options)stringHash(text, algorithm, encoding, options)
hashString(...)remains as a deprecated alias forstringHash(...).
Recommended replacement:
const digest = await fileHash(fileUri, {
algorithm: 'SHA-256',
});Cancelable flow:
const controller = new AbortController();
const promise = fileHash(fileUri, {
algorithm: 'SHA-256',
signal: controller.signal,
});
controller.abort();
await promise; // rejects with E_CANCELLED / AbortErrorFor keyed algorithms:
await fileHash(fileUri, {
algorithm: 'HMAC-SHA-256',
hashOptions: {
key: 'secret',
keyEncoding: 'utf8',
},
});Compatibility
- Hash output remains lowercase hex.
- Key rules are unchanged:
HMAC-*algorithms requirehashOptions.key.BLAKE3uses keyed mode only whenhashOptions.keyis provided.- Other algorithms reject
hashOptions.key.
HashOptions.moderemains removed and still rejects with
E_INVALID_ARGUMENT.XXH3-128remains native-only.- Consumers using the published package do not need Zig installed. Custom
source/prebuilt builds must use thezig-files-hashC ABI v3 core. - Cancellation is cooperative. Long file hashes stop at chunk boundaries; small
stringHashcalls can finish before an abort is observed.
Performance
- Refreshed physical-device Release benchmarks for the current
nativeand
zigengines. Full current tables live inBENCHMARKS.md. - The refreshed benchmark tables compare the current
zigengine with the
currentnativeengine. They should be read separately from the
release-to-release Zig speedups below. - Compared with the previous benchmark set, Zig
BLAKE3is much faster:- iOS 200 MiB:
728 ms->~302 ms - Android 200 MiB:
551 ms->~391 ms
- iOS 200 MiB:
- Zig
XXH3-64improved on iOS:81 ms->~66 msfor 200 MiB. - Zig
SHA-224/SHA-256and matching HMAC variants remain competitive on
iOS and stay near native on Android through the existing native fallback. - Native remains the faster choice for iOS
SHA-1and the iOS
SHA-384/SHA-512family. - On Android, Zig remains the faster choice for
SHA-512/224and
SHA-512/256; native remains faster forSHA-1,SHA-384,SHA-512,
BLAKE3, andXXH3-64in the current device run.
Testing
- Expanded Jest coverage for the object request API, default values, abort
handling, native cancellation calls, andAbortErrornormalization. - Updated runtime diagnostics tests for Zig C ABI v3 and
zig-files-hash
v0.0.5.
v2.0.3 - iOS Zig engine fix and React Native 0.85 template refresh
This release fixes iOS Zig engine prebuilts for Xcode 26 and refreshes the
project scaffold/example app to the latest create-react-native-library
template.
The public FileHash JavaScript API and hash output behavior are unchanged. The
default native engine remains unchanged; the iOS fix matters when opting into
the zig engine.
Fixed
- Fixed iOS
zigengine builds on Xcode 26 by repacking Zig-produced static
archives with Apple'slibtool, avoiding linker rejection of archives with
not 8-byte alignedMach-O members. - macOS CI now uses Homebrew
zig@0.15for Zig0.15.2, which includes the
Xcode 26.4.tbd/Dylib.zigbackport needed to rebuild iOS prebuilts.
Compatibility
- JavaScript API remains compatible with previous
2.xreleases. - Android minimum SDK remains
24(Android 7.0). - React Native development and example app baseline updated to
0.85.0. - React development baseline updated to
19.2.3. - Old Architecture compatibility remains available for older React Native
versions that still support it. - Old Architecture support is deprecated and will be removed in a future major
release. - Both
nativeandzigengine selection paths remain supported.
Android
- Updated the example Android project to the current React Native 0.85
template. - Updated example Gradle wrapper to
9.3.1. - Updated library Android defaults to
compileSdkVersion 36and
targetSdkVersion 36. - Kept Android minimum SDK at
24. - Kept Android NDK pinned to
27.1.12297006for reproducible CMake/JNI builds. - Moved library Android default versions into
android/build.gradleand removed
the separate libraryandroid/gradle.properties. - Migrated Android lint configuration from
lintOptionstolint. - Kept
check:16kbcoverage for the final Androidlibfilehash-native.so. - Kept native and Zig Android hashing behavior unchanged.
iOS
- Updated the example iOS project and pods for React Native 0.85.
- Updated iOS CI jobs to Xcode
26. - Enabled React Native prebuilt dependencies in CI for faster iOS builds.
- Included repacked Zig iOS prebuilts compatible with Xcode 26.
- Preserved the existing Objective-C++ FileHash implementation and bridge
exports.
Zig
- iOS Zig prebuilts are rebuilt with archive repacking for Apple's stricter
Xcode 26 linker checks. - Android Zig prebuilt generation remains based on Zig cross-compilation and is
unchanged.
Tooling and CI
- Updated
create-react-native-librarymetadata from0.55.1to0.62.0. - Updated Node tooling to Node
24.13.0in.nvmrc. - Updated Jest to
30.xwith@react-native/jest-presetand@jest/globals. - Updated TypeScript, ESLint, Prettier, Turbo, Bob, Commitlint, Lefthook, and
Release It dependencies to match the refreshed template. - Excluded generated Gradle/CMake output directories from Turbo Android inputs.
- Added
cppto packaged files for future native shared-code layout.
v2.0.2 - Packaging cleanup
Fixed
- Removed unnecessary runtime dependency on
buffer. - Package no longer pulls
bufferinto consumer installs; no API/runtime behavior changes.
v2.0.1 - Switchable engines (native / zig) and API update
Breaking changes
HashOptions.moderemoved from public API. Passingmodenow returnsE_INVALID_ARGUMENT.- HMAC moved to dedicated algorithms:
HMAC-SHA-224,HMAC-SHA-256,
HMAC-SHA-384,HMAC-SHA-512,HMAC-MD5,HMAC-SHA-1. - Keyed/plain selection for
BLAKE3is now inferred from presence ofkey. keyis now valid only for HMAC algorithms andBLAKE3; for other
algorithms it returnsE_INVALID_ARGUMENT.hashString(...)was replaced bystringHash(...)as the primary API.
hashString(...)remains as a deprecated alias for migration.- Output contract is fixed: both
fileHashandstringHashreturn lowercase
hex digest strings.
Added
- New optional
zigengine with stable Zig C ABI integration. - Build-time engine selection (
nativeby default, optionalzig) for Android
and iOS. - Runtime diagnostics APIs:
getRuntimeInfo()getRuntimeDiagnostics()
- Expo config plugin support (
app.plugin.js) to set engine in prebuild/EAS. - New benchmark document and size/perf helper scripts:
BENCHMARKS.mdscripts/compare-size-android.shscripts/compare-size-ios.sh
Changed
- Android engine internals split into explicit executors (
NativeHashEngine,
ZigHashEngine) with shared module routing. - Android Zig path now uses native fallback for
SHA-224/SHA-256and
matching HMAC variants in shipped generic Zig setup to avoid SHA-2 latency
cliffs on devices without ARM64sha2acceleration in prebuilt config. - iOS bridge refactored into dedicated internal helpers for native and Zig
paths (FileHashBridgeNative,FileHashBridgeZig,FileHashZigHelpers). fileHashsupport for provider-backed paths was hardened on both platforms
(content://on Android, security-scoped/provider URLs on iOS).
CI / Tooling
- Added reusable Zig setup action (
.github/actions/setup-zig). - Expanded CI coverage for native and Zig paths (including Android unit tests
and runtime smoke flows).
v1.1.3 - 16KB page alignment for Play Store
-
What's new
- Android: enable 16KB page alignment for native library to satisfy Play Store requirements.
- Guard the linker flag when unsupported; builds continue without 16KB alignment.
- README: document 16KB alignment and tested NDK (27.1.x).
-
Tooling
- Bump Yarn to 4.12.0 and refresh example locks.
v1.1.2 – bundle native sources in npm package
Fix
- Include vendored native sources (xxhash/blake3) in the npm tarball so iOS builds from npm no longer fail with
xxhash.h file not found.
Notes
- After clone from git:
git submodule update --init --recursive.
v1.1.1 – bundle native sources (XXH3/BLAKE3, HMAC/keyed)
Fix
- Bundled native sources (xxhash/blake3) in the npm package so iOS builds no longer fail with
xxhash.h file not foundand the TurboModule registers correctly.
Reminder (from 1.1.0)
- Native XXH3-64/XXH3-128 and BLAKE3 on iOS/Android.
hashString(text, algorithm, encoding?, options?)for small payloads (utf8/base64); for real files usefileHash(streams from disk).- Modes in
fileHash/hashString:hash/hmac(SHA-224/256/384/512) /keyed(BLAKE3, 32-byte key utf8/hex/base64). - XXH3-128 output matches official xxHash order (low64 → high64).
- Example app: hash file/string, switch modes, test utf8/hex/base64 keys. Migrated to
create-react-native-librarytemplate (TurboModule, new/old arch). - README: algorithm table, output lengths, thread-safety note, submodule reminder.
Notes
- After clone:
git submodule update --init --recursive. - Tests:
yarn test.
v1.1.0 – XXH3 & BLAKE3, hashString, HMAC/keyed modes
-
What’s new
- Added native XXH3-64/XXH3-128 and BLAKE3 on iOS/Android.
- New
hashString(text, algorithm, encoding?, options?)for small payloads. Supportsutf8andbase64input. For real files always preferfileHash, which streams data from disk. - Modes supported in
fileHashandhashString:hash/hmac/keyed- HMAC — SHA-224/256/384/512 only.
- Keyed — BLAKE3 only, 32-byte key (
utf8/hex/base64).
- XXH3-128 output matches the official xxHash order (low64 → high64) on both platforms.
-
Example & scaffolding
- New example app: hash files or small strings, switch modes (
hash/hmac/keyed), and tryutf8/hex/base64keys. - Project migrated to the
create-react-native-librarytemplate (TurboModule, supports new/old architecture). - README: algorithm table and output lengths, thread-safety note, reminder about submodules.
- New example app: hash files or small strings, switch modes (
-
Notes
- After clone:
git submodule update --init --recursive. - Tests:
yarn test.
- After clone:
v1.0.5 — Full hash suite, Android coroutines, iOS performance
-
Highlights
- Adds MD5, SHA‑1, SHA‑224, SHA‑256, SHA‑384, SHA‑512 across Android and iOS.
- Faster async: Android coroutines; iOS OperationQueue + 64 KiB chunks.
- README updated; CI now publishes only to npmjs.com.
-
Android
- Migrated to Kotlin coroutines with lifecycle-aware cancel in
invalidate(). - Supports
file://,content://, and plain paths; 64 KiB buffer for large files. - Explicit mapping to JCA names; unsupported →
E_UNSUPPORTED_ALGORITHM.
- Migrated to Kotlin coroutines with lifecycle-aware cancel in
-
iOS
- Uses
OperationQueue(maxConcurrentOperationCount = 2) and 64 KiB chunked reads. - SHA‑224 via CommonCrypto (CryptoKit doesn’t provide SHA‑224).
- Thin Obj‑C extern (
RCT_EXTERN_MODULE) kept for Old/New Arch robustness.
- Uses
-
JS/Types
THashAlgorithm:'MD5' | 'SHA-1' | 'SHA-224' | 'SHA-256' | 'SHA-384' | 'SHA-512'(default'SHA-256').
-
Docs/CI
- README documents all algorithms and examples.
- Publishing to GitHub Packages removed to avoid registry conflicts.
-
Breaking changes
- None expected. Public API unchanged; types widened to include more algorithms.
-
Upgrade notes
- If
.npmrcpoints@preeternalto GitHub Packages, switch to npmjs.com. - iOS: run
pod installafter upgrading. - Android: ensure
kotlinx-coroutines-androidis available in your build.
- If
v1.0.4
- Fixed compatibility with React Native New Architecture (TurboModules) on Android.
- Now the library works seamlessly with both legacy and new architectures.
- Improved module registration and codegen integration for Android.
- Minor internal refactoring.
Full Changelog: v1.0.2...v1.0.4