Skip to content

Commit 070e347

Browse files
isaacrowntreeclaude
andcommitted
docs: rename 0.4.0 -> 0.5.0 across all docs after release-it minor bump
release-it auto-incremented 0.4.0 -> 0.5.0 because the @release-it/conventional-changelog plugin saw `feat:` commits in the range since v0.3.1 and inferred a minor bump. The published artefact on npm is therefore `react-native-nitro-unzip@0.5.0` (latest), not 0.4.0. All CHANGELOG, README, docusaurus, and TypeScript-spec docstring references that named 0.4.0 are renamed accordingly so the docs match the npm/git-tag reality. Anchor links (`#transactional-behaviour-040`, `#whats-new-in-040`) updated to the new heading slugs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 35d0dde commit 070e347

9 files changed

Lines changed: 21 additions & 21 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Changelog
22

3-
## 0.4.0 — Cross-platform security hardening (Android NIO/ZipFile + iOS ZIPFoundation)
3+
## 0.5.0 — Cross-platform security hardening (Android NIO/ZipFile + iOS ZIPFoundation)
44

55
**Breaking changes** — please read before upgrading.
66

@@ -54,7 +54,7 @@ with iOS/Swift primitives (not a Java translation):
5454
- **Password ZIP crypto upgraded to AES-256 on iOS.** 0.3 used
5555
SSZipArchive's `withPassword:` overload which writes traditional
5656
PKWARE encryption — broken, crackable in minutes with modern tools.
57-
0.4.0 uses SSZipArchive's `aes: true` overload to match Android's
57+
0.5.0 uses SSZipArchive's `aes: true` overload to match Android's
5858
AES-256 strength. Cross-platform password archives now have
5959
equivalent crypto.
6060
- **Mid-extraction cancellation on the password path now reads the
@@ -114,7 +114,7 @@ with iOS/Swift primitives (not a Java translation):
114114
`createDirectory(withIntermediateDirectories: true)` (iOS) and
115115
`Files.createDirectories` (Android) created every missing parent in
116116
one call, but rollback only knew about the leaf — orphaned empty
117-
parents survived. 0.4.0 walks ancestry one level at a time and
117+
parents survived. 0.5.0 walks ancestry one level at a time and
118118
records each created directory.
119119
- **Write errors propagate instead of being silently swallowed.** The
120120
iOS unzip path used `try? handle.write(contentsOf:)` inside the

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ High-performance ZIP operations for React Native, powered by [Nitro Modules](htt
1313

1414
## Features
1515

16-
- **Fast**~9,000+ files/sec on Android (post-NIO / `java.util.zip.ZipFile` migration in 0.4.0) and ~10,000+ files/sec on iOS (`O_NOFOLLOW` streaming writes), measured on nested 1000-entry archives on dev hardware
16+
- **Fast**~9,000+ files/sec on Android (post-NIO / `java.util.zip.ZipFile` migration in 0.5.0) and ~10,000+ files/sec on iOS (`O_NOFOLLOW` streaming writes), measured on nested 1000-entry archives on dev hardware
1717
- **Zero bridge overhead** — progress callbacks via JSI, no serialization
1818
- **Cancellable** — mid-write cancellation on Android (`Thread.interrupt()` + interruptible NIO channels), per-entry cancellation on iOS (Swift Concurrency)
1919
- **AES-256 password support** — encrypted archives, zip & unzip, on both platforms
@@ -28,11 +28,11 @@ npm install react-native-nitro-unzip react-native-nitro-modules
2828
cd ios && pod install
2929
```
3030

31-
> Requires React Native 0.75+, [Nitro Modules](https://nitro.margelo.com/) 0.35+, iOS 15.5+, **Android minSdk 26+** (since 0.4.0), and Java 17 (Android).
31+
> Requires React Native 0.75+, [Nitro Modules](https://nitro.margelo.com/) 0.35+, iOS 15.5+, **Android minSdk 26+** (since 0.5.0), and Java 17 (Android).
3232
33-
### Security defences (0.4.0+)
33+
### Security defences (0.5.0+)
3434

35-
The 0.4.0 release added the same Zip Slip / symlink / case-collision /
35+
The 0.5.0 release added the same Zip Slip / symlink / case-collision /
3636
BiDi-spoofing defences to **both Android and iOS**:
3737

3838
- Path traversal (`../escape`), absolute paths, backslash separators

docs/docs/getting-started.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ react-native-nitro-unzip provides high-performance ZIP extraction and compressio
1313
| React Native | 0.75+ |
1414
| Nitro Modules | 0.35+ |
1515
| iOS | 15.5+ |
16-
| Android SDK | **26+** (bumped in 0.4.0 — `java.nio.file` requires API 26) |
16+
| Android SDK | **26+** (bumped in 0.5.0 — `java.nio.file` requires API 26) |
1717
| Java (Android) | 17 |
1818

1919
:::info New Architecture Required
@@ -39,7 +39,7 @@ The underlying `SSZipArchive` dependency requires **iOS 15.5+**. Set your deploy
3939

4040
### Android
4141

42-
No additional setup needed — the library auto-links with React Native. Your app must be built with **Java 17** (the RN 0.73+ default) and target **`minSdkVersion 26`** or higher (bumped from 21 in 0.4.0 because the extraction path uses `java.nio.file.Path` / `Files` / `FileChannel`, which require API 26).
42+
No additional setup needed — the library auto-links with React Native. Your app must be built with **Java 17** (the RN 0.73+ default) and target **`minSdkVersion 26`** or higher (bumped from 21 in 0.5.0 because the extraction path uses `java.nio.file.Path` / `Files` / `FileChannel`, which require API 26).
4343

4444
## Quick Start
4545

docs/docs/performance.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ react-native-nitro-unzip is designed for speed. Here's how it performs and why.
88

99
## Benchmarks
1010

11-
### 0.4.0 nested perf smoke (1000 entries across ~512 unique dirs)
11+
### 0.5.0 nested perf smoke (1000 entries across ~512 unique dirs)
1212

1313
Measured on dev hardware. Reflects realistic workloads (tile sets, asset bundles, SDK archives) — files spread across deep directory trees with many shared parent prefixes, not a flat archive.
1414

@@ -17,7 +17,7 @@ Measured on dev hardware. Reflects realistic workloads (tile sets, asset bundles
1717
| Android (post-NIO) | ~8,300 files/sec | ~120 ms |
1818
| iOS (`O_NOFOLLOW` streaming write) | ~10,000+ files/sec | ~100 ms |
1919

20-
The Android number is a **20× improvement** over the 0.3.x `ZipInputStream`-based path (~474 files/sec). The full 0.4.0 migration ([details](#whats-new-in-040)) is what made it possible.
20+
The Android number is a **20× improvement** over the 0.3.x `ZipInputStream`-based path (~474 files/sec). The full 0.5.0 migration ([details](#whats-new-in-050)) is what made it possible.
2121

2222
## Why It's Fast
2323

@@ -27,7 +27,7 @@ The Android number is a **20× improvement** over the 0.3.x `ZipInputStream`-bas
2727
- **POSIX `open(O_NOFOLLOW | O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC)`** for writes — eliminates the per-file `resolvingSymlinksInPath()` syscall the URL-based path would otherwise pay on every entry. Critical for nested archives where every leaf would otherwise re-stat its ancestors.
2828
- [**SSZipArchive**](https://github.com/ZipArchive/ZipArchive) is retained ONLY for password-protected paths (read + write), since ZIPFoundation has no AES support.
2929

30-
### Android (0.4.0 NIO migration)
30+
### Android (0.5.0 NIO migration)
3131

3232
- **`java.util.zip.ZipFile`** for random-access central-directory reads — no inflate to enumerate headers, no TOCTOU window between validate and extract passes (single FD).
3333
- **`java.nio.file.FileChannel.open(..., NOFOLLOW_LINKS)` + `Channels.newOutputStream(...)`** — typed exceptions (`AccessDeniedException`, `NoSuchFileException`, `FileAlreadyExistsException`), interruptible writes, and proper symlink refusal.
@@ -41,9 +41,9 @@ The Android number is a **20× improvement** over the 0.3.x `ZipInputStream`-bas
4141
- **Background execution** — extraction runs on native background threads / Swift `Task`s, keeping the UI responsive. iOS also registers a `UIApplication.beginBackgroundTask` so the OS doesn't suspend the app mid-archive.
4242
- **Transactional**: a mid-stream failure rolls every created file and intermediate directory back, so the destination is never left in a partial-but-looks-complete state.
4343

44-
## What's new in 0.4.0
44+
## What's new in 0.5.0
4545

46-
| Subsystem | 0.3.x | 0.4.0 |
46+
| Subsystem | 0.3.x | 0.5.0 |
4747
|---|---|---|
4848
| Android engine | `ZipInputStream` (streaming-decode) | `java.util.zip.ZipFile` (random-access central directory) |
4949
| Android writes | `File` + `FileOutputStream` | `java.nio.file.FileChannel` + `Channels.newOutputStream` (NIO) |

docs/docs/usage/cancellation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ task.cancel();
2222

2323
Cancellation is **synchronous** — it happens immediately via JSI with no bridge round-trip. The `await()` promise will reject when a task is cancelled.
2424

25-
**0.4.0 — mid-write cancellation actually fires.** On Android, `cancel()` triggers `Thread.interrupt()` via `runInterruptible`, which unsticks an in-flight `FileChannel` write on the next syscall (not the next chunk boundary). On iOS, `Task.checkCancellation()` runs between every entry, so a cancel between entries halts immediately. In both cases the partial state is then rolled back before the promise rejects — see [Transactional behaviour](./extraction#transactional-behaviour-040).
25+
**0.5.0 — mid-write cancellation actually fires.** On Android, `cancel()` triggers `Thread.interrupt()` via `runInterruptible`, which unsticks an in-flight `FileChannel` write on the next syscall (not the next chunk boundary). On iOS, `Task.checkCancellation()` runs between every entry, so a cancel between entries halts immediately. In both cases the partial state is then rolled back before the promise rejects — see [Transactional behaviour](./extraction#transactional-behaviour-050).
2626

2727
**`cancel()` before `await()` is a no-op.** If you cancel a task you haven't `await()`'d yet, the next `await()` proceeds normally. This avoids the 0.3-era footgun where a pre-await cancel permanently poisoned the task.
2828

docs/docs/usage/compression.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ if (result.success) {
6767
| `averageSpeed` | `number` | Average files per second |
6868
| `totalBytes` | `number` | Total bytes written to the zip file |
6969

70-
:::note Empty directory preservation (0.4.0+)
70+
:::note Empty directory preservation (0.5.0+)
7171
Empty placeholder directories in the source (e.g. `cache/`, `logs/today/`) are preserved as trailing-slash entries in the archive, so a zip → unzip round trip keeps them. They do **not** count toward `compressedFiles` / `totalFiles` — those fields use the same files-only semantics as the unzip-side `extractedFiles` / `totalFiles`, so cross-platform round-trip counts match.
7272
:::

docs/docs/usage/extraction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ unzip.extract('/path/to/archive.zip', '/output');
9999

100100
`content://` URIs (returned by Android's Storage Access Framework) are **not** accepted — resolve them to a filesystem path first.
101101

102-
## Transactional behaviour (0.4.0+)
102+
## Transactional behaviour (0.5.0+)
103103

104104
Extraction is **all-or-nothing**. If anything fails after the first byte is written — a corrupt archive entry, the disk filling up, a write error, or cancellation between entries — the library rolls back every file AND every intermediate directory it created before re-throwing.
105105

docs/docs/usage/password.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ const result = await task.await();
4444
| Platform | Encryption (write) | Encryption (read) |
4545
|---|---|---|
4646
| Android | **AES-256** via [zip4j](https://github.com/srikanth-lingala/zip4j) | AES-256 + traditional PKWARE (zip4j) |
47-
| iOS (0.4.0+) | **AES-256** via [SSZipArchive](https://github.com/ZipArchive/ZipArchive)'s `aes: true` overload | AES-256 + traditional PKWARE (SSZipArchive) |
47+
| iOS (0.5.0+) | **AES-256** via [SSZipArchive](https://github.com/ZipArchive/ZipArchive)'s `aes: true` overload | AES-256 + traditional PKWARE (SSZipArchive) |
4848

49-
:::tip 0.4.0 — iOS now writes AES-256
50-
0.3.x used SSZipArchive's `withPassword:` overload on iOS, which writes **traditional PKWARE encryption** — broken and crackable in minutes with modern tools. 0.4.0 switches to the `aes: true` overload, matching Android's AES-256 strength. Cross-platform password archives now have equivalent crypto strength.
49+
:::tip 0.5.0 — iOS now writes AES-256
50+
0.3.x used SSZipArchive's `withPassword:` overload on iOS, which writes **traditional PKWARE encryption** — broken and crackable in minutes with modern tools. 0.5.0 switches to the `aes: true` overload, matching Android's AES-256 strength. Cross-platform password archives now have equivalent crypto strength.
5151
:::
5252

5353
:::note Cross-platform compatibility

src/specs/Unzip.nitro.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export interface Unzip
185185
* Create a password-protected ZIP archive from a directory.
186186
* Uses AES-256 encryption on both Android (via zip4j) and iOS (via
187187
* SSZipArchive's AES variant). 0.3 used weak PKWARE-traditional
188-
* encryption on iOS; 0.4.0 brings cross-platform AES-256 parity.
188+
* encryption on iOS; 0.5.0 brings cross-platform AES-256 parity.
189189
*
190190
* @param sourcePath - Absolute path to the directory to compress
191191
* @param destinationZipPath - Absolute path for the output ZIP file

0 commit comments

Comments
 (0)