Skip to content

Releases: Preeternal/react-native-file-hash

v2.0.8 - Zig fd/path hashing and mmap request hint

Choose a tag to compare

@Preeternal Preeternal released this 11 Jul 20:19

Added

  • Added HashRequest.mmap as an opt-in file hashing hint for stable regular
    local files. The option maps to Zig C ABI v4 ZFH_OPTION_USE_MMAP, is a
    no-op in the default native engine, is ignored for Zig
    descriptor/stream-backed sources, and is rejected by stringHash.

Changed

  • Updated the bundled Zig core integration to zig-files-hash v0.0.7 / C ABI
    v4.
  • The Zig Android engine now hashes local paths through zfh_context_file_hash
    and Android content:// descriptors through zfh_fd_hash, keeping the read
    loop inside Zig when a path or fd is available. The default native Android
    engine still uses platform stream/file-handle hashing.
  • The Zig iOS/macOS bridge now uses zfh_context_file_hash for local paths and
    tries coordinated path/fd hashing for file URLs before falling back to
    NSInputStream streaming. The default iOS native engine still uses the
    platform file-handle implementation.

v2.0.7 - Desktop support and leaner npm package

Choose a tag to compare

@Preeternal Preeternal released this 06 Jul 19:24

This release line starts desktop support for React Native out-of-tree
platforms. macOS support lands through react-native-macos; React Native
Windows support lands through react-native-windows.

Added

  • Added experimental macOS support for react-native-macos.
  • Added a separate macOS example workspace in examples/macos.
  • Added a macOS Zig prebuilt xcframework at
    third_party/zig-files-hash-prebuilt/macos/ZigFilesHash.xcframework.
  • Added scripts/build-zig-macos.sh for rebuilding the macOS Zig prebuilt.
  • Added experimental Windows support for react-native-windows.
  • Added a separate Windows example workspace in examples/windows.
  • Added Windows Zig prebuilt .lib artifacts for Win32, x64, and ARM64
    at third_party/zig-files-hash-prebuilt/windows.
  • Added scripts/build-zig-windows.sh for rebuilding Windows Zig prebuilts.
  • Added desktop development notes and workspace commands to CONTRIBUTING.md.
  • Added release benchmark snapshots for experimental macOS and Windows Zig
    desktop support to BENCHMARKS.md.
  • Added platform status badges and short desktop support links to README.md.

Changed

  • The podspec now declares both iOS and macOS platforms.
  • macOS uses the Zig engine only. The native Apple engine switch remains iOS
    specific.
  • Windows uses the Zig engine only. There is no Windows native-engine switch.
  • Updated the bundled Zig core to zig-files-hash v0.0.6. Windows Zig
    prebuilts are rebuilt with bundled compiler-rt so MSVC consumers do not hit
    unresolved runtime helpers such as __divti3 when linking
    zig_files_hash.lib.
  • iOS and macOS Zig xcframework builds now expose only the C API headers in
    their Headers directories instead of the full Zig source tree.
  • The npm package allowlist now separates repository build inputs from
    consumer package contents. Source submodules remain in the repository for
    maintainers, while npm users receive only the native build inputs needed by
    Gradle/CocoaPods.
  • The npm package no longer includes large unused upstream directories such as
    third_party/xxhash/tests, third_party/xxhash/cli,
    third_party/blake3/src, third_party/blake3/benches, and
    third_party/zig-files-hash/src/*.zig.
  • scripts/check-packed-prebuilts.sh now verifies the minimal required
    third-party artifacts and fails if unnecessary third-party source/test
    directories re-enter the packed tarball.
  • The Windows example uses the Hermes compiler from the React Native Windows
    Hermes NuGet package for release bundling, keeping the generated bytecode
    aligned with the RNW runtime used by the app.

Package size

Local npm pack --dry-run --json numbers after this cleanup and the Windows
prebuilt addition:

  • package entries: 310 -> 106
  • unpacked size: 24.35 MB -> 23.24 MB
  • tarball size: 5.75 MB -> 5.98 MB

The tarball is slightly larger than before because this release adds three
Windows .lib prebuilts. The cleanup still removes unused upstream sources and
keeps the shipped payload focused on required native build inputs. Most of the
remaining package size is the expected Zig prebuilt payload for Android, iOS,
macOS, and Windows.

v2.0.6 - Seeded XXH3

Choose a tag to compare

@Preeternal Preeternal released this 24 Jun 17:15

This release adds optional seeded XXH3-64 / XXH3-128 support.

A seed is useful when an app needs reproducible non-cryptographic checksums
across a backend, CLI tooling, and React Native. For example, a backend can
publish both the expected XXH3 digest and the exact u64 seed used to compute
it; the mobile app can then hash the downloaded local file with the same seed
and compare the result.

Seeded XXH3 is also useful for app-owned cache or deduplication namespaces,
such as media-cache-v1 or upload-dedupe-v2, where the same bytes should
produce stable hashes within that namespace.

Seeds are not secrets and do not make XXH3 cryptographic. Use HMAC or keyed
BLAKE3 when authenticity matters.

Added

  • Added hashOptions.seed for XXH3-64 and XXH3-128 in both fileHash and
    stringHash.
  • hashOptions.seed accepts:
    • bigint
    • non-negative safe integer number
    • decimal string
    • 0x hex string
  • Added xxh3SeedFromLabel(label) for deterministic UTF-8 label -> u64 seed
    derivation using FNV-1a 64-bit. It returns a canonical 0x hex seed that can
    be passed directly to hashOptions.seed.
  • Added seeded XXH3 coverage to the example app, including label, string,
    number, and bigint seed inputs.
  • Added seeded XXH3 validation and vector tests.

Usage

Pass large u64 seeds from a backend as strings so JavaScript does not round
them:

const manifest = {
  xxh3Seed: '12345678901234567890',
  xxh3: '4b5e0a417dfa7ed2fb965bc17c16bd34',
};

const actual = await fileHash(localFileUri, {
  algorithm: 'XXH3-128',
  hashOptions: {
    seed: manifest.xxh3Seed,
  },
});

if (actual !== manifest.xxh3) {
  throw new Error('Downloaded file failed checksum verification');
}

For app-owned namespaces, derive a stable seed from a readable label:

const seed = xxh3SeedFromLabel('media-cache-v1');

const cacheKey = await fileHash(fileUri, {
  algorithm: 'XXH3-128',
  hashOptions: { seed },
});

Compatibility

  • hashOptions.seed is optional. Omit it for regular unseeded XXH3.
  • hashOptions.seed is only valid for XXH3-64 and XXH3-128; other
    algorithms reject it.
  • Large seeds above Number.MAX_SAFE_INTEGER should be passed as bigint,
    decimal string, or 0x hex string.
  • With the optional zig engine, seeded XXH3 currently means XXH3-64;
    XXH3-128 remains native-only.

v2.0.5 - Zig C ABI v3, streaming files, and cancellation

Choose a tag to compare

@Preeternal Preeternal released this 14 Jun 17:36

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
    HashAbortError TypeScript types.
  • Added optional AbortSignal support for cancelling work the app no longer
    needs. Aborting rejects with E_CANCELLED and normalizes the JS error name
    to AbortError.
  • Added native cancelOperation(operationId) plumbing behind the JS API.
    Operation ids are internal; users should cancel with AbortController.
  • Added cancellation coverage for file hashing and string hashing in both
    engines:
    • Android native engine checks cancellation between stream chunks and closes
      the active InputStream on cancel.
    • Android Zig engine forwards cancellation into the Zig operation state.
    • iOS native engine tracks Operation instances and rejects cancelled work
      with E_CANCELLED.
    • iOS Zig engine tracks operations and forwards cancellation into the Zig
      operation state.
  • 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 feeds zfh_hasher_*.
    • iOS Zig streams file URLs/paths through zfh_hasher_*.
    • Native engines continue to stream file data from disk.
  • Updated the bundled Zig core to zig-files-hash v0.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) and fileHash(path, {}) both default to SHA-256.
  • stringHash(text) and stringHash(text, {}) both default to SHA-256 with
    utf8 input 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.sh now 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 for stringHash(...).

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 / AbortError

For 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 require hashOptions.key.
    • BLAKE3 uses keyed mode only when hashOptions.key is provided.
    • Other algorithms reject hashOptions.key.
  • HashOptions.mode remains removed and still rejects with
    E_INVALID_ARGUMENT.
  • XXH3-128 remains native-only.
  • Consumers using the published package do not need Zig installed. Custom
    source/prebuilt builds must use the zig-files-hash C ABI v3 core.
  • Cancellation is cooperative. Long file hashes stop at chunk boundaries; small
    stringHash calls can finish before an abort is observed.

Performance

  • Refreshed physical-device Release benchmarks for the current native and
    zig engines. Full current tables live in BENCHMARKS.md.
  • The refreshed benchmark tables compare the current zig engine with the
    current native engine. They should be read separately from the
    release-to-release Zig speedups below.
  • Compared with the previous benchmark set, Zig BLAKE3 is much faster:
    • iOS 200 MiB: 728 ms -> ~302 ms
    • Android 200 MiB: 551 ms -> ~391 ms
  • Zig XXH3-64 improved on iOS: 81 ms -> ~66 ms for 200 MiB.
  • Zig SHA-224 / SHA-256 and 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-1 and the iOS
    SHA-384 / SHA-512 family.
  • On Android, Zig remains the faster choice for SHA-512/224 and
    SHA-512/256; native remains faster for SHA-1, SHA-384, SHA-512,
    BLAKE3, and XXH3-64 in the current device run.

Testing

  • Expanded Jest coverage for the object request API, default values, abort
    handling, native cancellation calls, and AbortError normalization.
  • 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

Choose a tag to compare

@Preeternal Preeternal released this 10 May 19:07

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 zig engine builds on Xcode 26 by repacking Zig-produced static
    archives with Apple's libtool, avoiding linker rejection of archives with
    not 8-byte aligned Mach-O members.
  • macOS CI now uses Homebrew zig@0.15 for Zig 0.15.2, which includes the
    Xcode 26.4 .tbd / Dylib.zig backport needed to rebuild iOS prebuilts.

Compatibility

  • JavaScript API remains compatible with previous 2.x releases.
  • 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 native and zig engine 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 36 and
    targetSdkVersion 36.
  • Kept Android minimum SDK at 24.
  • Kept Android NDK pinned to 27.1.12297006 for reproducible CMake/JNI builds.
  • Moved library Android default versions into android/build.gradle and removed
    the separate library android/gradle.properties.
  • Migrated Android lint configuration from lintOptions to lint.
  • Kept check:16kb coverage for the final Android libfilehash-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-library metadata from 0.55.1 to 0.62.0.
  • Updated Node tooling to Node 24.13.0 in .nvmrc.
  • Updated Jest to 30.x with @react-native/jest-preset and @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 cpp to packaged files for future native shared-code layout.

v2.0.2 - Packaging cleanup

Choose a tag to compare

@Preeternal Preeternal released this 19 Mar 19:53

Fixed

  • Removed unnecessary runtime dependency on buffer.
  • Package no longer pulls buffer into consumer installs; no API/runtime behavior changes.

v2.0.1 - Switchable engines (native / zig) and API update

Choose a tag to compare

@Preeternal Preeternal released this 15 Mar 14:54

Breaking changes

  • HashOptions.mode removed from public API. Passing mode now returns E_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 BLAKE3 is now inferred from presence of key.
  • key is now valid only for HMAC algorithms and BLAKE3; for other
    algorithms it returns E_INVALID_ARGUMENT.
  • hashString(...) was replaced by stringHash(...) as the primary API.
    hashString(...) remains as a deprecated alias for migration.
  • Output contract is fixed: both fileHash and stringHash return lowercase
    hex digest strings.

Added

  • New optional zig engine with stable Zig C ABI integration.
  • Build-time engine selection (native by default, optional zig) 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.md
    • scripts/compare-size-android.sh
    • scripts/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-256 and
    matching HMAC variants in shipped generic Zig setup to avoid SHA-2 latency
    cliffs on devices without ARM64 sha2 acceleration in prebuilt config.
  • iOS bridge refactored into dedicated internal helpers for native and Zig
    paths (FileHashBridgeNative, FileHashBridgeZig, FileHashZigHelpers).
  • fileHash support 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

Choose a tag to compare

@Preeternal Preeternal released this 25 Jan 11:19
  • 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

Choose a tag to compare

@Preeternal Preeternal released this 09 Jan 18:31

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)

Choose a tag to compare

@Preeternal Preeternal released this 14 Dec 18:38

Fix

  • Bundled native sources (xxhash/blake3) in the npm package so iOS builds no longer fail with xxhash.h file not found and 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 use fileHash (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-library template (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.