Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @JimmyDaddy
49 changes: 49 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Bug report
description: Report a reproducible runtime, build, packaging, or documentation defect.
title: '[Bug]: '
labels:
- bug
body:
- type: checkboxes
attributes:
label: Before submitting
options:
- label: I searched existing issues and read the troubleshooting guide.
required: true
- label: This report does not contain sensitive files or a security vulnerability.
required: true
- type: input
attributes:
label: Package version
placeholder: 0.2.0
validations:
required: true
- type: dropdown
attributes:
label: Runtime
options:
- Android legacy architecture
- Android New Architecture
- iOS legacy architecture
- iOS New Architecture
- React Native Web
validations:
required: true
- type: input
attributes:
label: React Native and bundler versions
description: Include React Native, browser, Metro, Webpack, or Vite versions that apply.
validations:
required: true
- type: textarea
attributes:
label: Reproduction
description: Provide minimal code, exact commands, and non-sensitive input sizes.
validations:
required: true
- type: textarea
attributes:
label: Expected and actual behavior
description: Include the complete error code and message when available.
validations:
required: true
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/JimmyDaddy/react-native-bs-diff-patch/security/advisories/new
about: Report security issues privately through GitHub.
- name: Documentation
url: https://bs-dff-patch.corerobin.com/docs/
about: Check setup, API, platform, and troubleshooting guidance first.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Feature request
description: Propose a focused addition to the public API, runtime support, or tooling.
title: '[Feature]: '
labels:
- enhancement
body:
- type: textarea
attributes:
label: Problem
description: Describe the user problem and the affected runtime.
validations:
required: true
- type: textarea
attributes:
label: Proposed behavior
description: Explain the desired API or workflow, including compatibility expectations.
validations:
required: true
- type: textarea
attributes:
label: Alternatives considered
validations:
required: false
23 changes: 23 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Summary

<!-- What changes, and why? -->

## Runtime impact

- [ ] Android legacy architecture
- [ ] Android New Architecture
- [ ] iOS legacy architecture
- [ ] iOS New Architecture
- [ ] React Native Web
- [ ] Documentation or tooling only

## Verification

<!-- List the exact commands and device/browser checks run. -->

## Checklist

- [ ] Public API changes include TypeScript declarations and bilingual docs.
- [ ] Native C changes include malformed-input coverage and a rebuilt WebAssembly bundle.
- [ ] Compatibility or behavior changes include focused regression tests.
- [ ] The packed npm artifact was inspected when package contents changed.
34 changes: 34 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
time: '03:00'
timezone: Asia/Shanghai
open-pull-requests-limit: 5
groups:
development-dependencies:
dependency-type: development
update-types:
- minor
- patch

- package-ecosystem: bundler
directory: /example
schedule:
interval: monthly
day: monday
time: '03:30'
timezone: Asia/Shanghai
open-pull-requests-limit: 3

- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
day: monday
time: '04:00'
timezone: Asia/Shanghai
open-pull-requests-limit: 3
75 changes: 72 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,16 @@ jobs:
site=true
web=true
;;
src/**|cpp/**|assets/**)
src/**|assets/**)
android=true
ios=true
quality=true
web=true
;;
cpp/fuzz/**|scripts/test-native-fuzz.sh)
quality=true
;;
cpp/**)
android=true
ios=true
quality=true
Expand All @@ -71,6 +80,10 @@ jobs:
android=true
quality=true
;;
compatibility/android-api/**|scripts/test-rn-android-compatibility.sh)
android=true
quality=true
;;
ios/**|example/ios/**|*.podspec)
ios=true
quality=true
Expand All @@ -80,14 +93,28 @@ jobs:
ios=true
quality=true
;;
web/**|scripts/build-web-wasm.sh|scripts/test-web*.mjs|scripts/web-*)
web/**|fixtures/**|scripts/build-web-wasm.sh|scripts/test-web*.mjs|scripts/web-*)
android=true
ios=true
web=true
quality=true
site=true
;;
scripts/prepare-package.mjs|scripts/test-package-consumers.mjs)
quality=true
web=true
;;
benchmarks/**|scripts/benchmark-web.mjs)
quality=true
site=true
web=true
;;
site/**|docs/**|README*.md|CONTRIBUTING.md|scripts/build-site.mjs|scripts/test-site*.mjs|.github/workflows/pages.yml)
site=true
;;
.github/ISSUE_TEMPLATE/**|.github/PULL_REQUEST_TEMPLATE.md|.github/CODEOWNERS|.github/dependabot.yml)
quality=true
;;
*.md)
site=true
;;
Expand Down Expand Up @@ -238,6 +265,36 @@ jobs:
if-no-files-found: ignore
retention-days: 7

android-rn-compatibility:
name: Android RN API Compatibility (${{ matrix.react-native }})
needs: changes
if: needs.changes.outputs.android == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: true
max-parallel: 2
matrix:
react-native: ['0.73.11', '0.74.7', '0.86.0']
steps:
- name: Checkout the code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7

- name: Set up JDK
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
with:
distribution: zulu
java-version: 17

- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6
with:
cache-provider: basic
cache-read-only: ${{ github.event_name == 'pull_request' }}

- name: Compile library against React Native Android APIs
run: sh scripts/test-rn-android-compatibility.sh ${{ matrix.react-native }} new

ios-build-test:
name: iOS (newArch=${{ matrix.new-arch }})
needs: changes
Expand Down Expand Up @@ -331,6 +388,7 @@ jobs:
yarn test:web
yarn test:web:browser
yarn test:web:metro
yarn test:package

- name: Verify npm package contents
run: npm pack --dry-run --ignore-scripts
Expand All @@ -354,6 +412,7 @@ jobs:
yarn typecheck
yarn lint
yarn test --runInBand
FUZZ_RUNS=2000 yarn test:fuzz

site-test:
name: Documentation Site and Playground Test
Expand All @@ -380,7 +439,17 @@ jobs:

ci-complete:
name: Complete CI
needs: [changes, quality, android-build, android-api-level-test, ios-build-test, web-test, site-test]
needs:
[
changes,
quality,
android-build,
android-api-level-test,
android-rn-compatibility,
ios-build-test,
web-test,
site-test,
]
if: always()
runs-on: ubuntu-latest
timeout-minutes: 5
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ jobs:
yarn typecheck
yarn lint
yarn test --runInBand
FUZZ_RUNS=2000 yarn test:fuzz
yarn test:web
yarn test:web:browser
yarn test:web:metro
yarn test:package
npm pack --dry-run --ignore-scripts
env:
CHROME_PATH: /usr/bin/google-chrome
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Changelog

All notable changes to this project are documented in this file. Releases use
[Semantic Versioning](https://semver.org/) and are generated from Conventional
Commits by release-it.

## [0.1.0](https://github.com/JimmyDaddy/react-native-bs-diff-patch/releases/tag/v0.1.0) (2026-07-18)

### Features

- add React Native Web support backed by WebAssembly and module Workers;
- support both the React Native legacy and New Architecture runtimes;
- add Android and iOS device-level runtime assertions;
- publish through npm Trusted Publishing with provenance;
- add bilingual documentation, an interactive Playground, and GitHub Pages.
46 changes: 32 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ all use the compatible `ENDSLEY/BSDIFF43` wire format.
- **One patch format:** generate on one supported runtime and apply on another.
- **Both React Native architectures:** legacy bridge and TurboModule/New Architecture.
- **Responsive by default:** native work uses dedicated serial queues; Web work
runs in an isolated module Worker.
reuses a module Worker and cached WebAssembly instance off the page thread.
- **Bound untrusted Web work:** built-in cancellation and input/output byte
limits reject predictably with stable error codes.
- **No Web service required:** the browser implementation is the same bundled C
core compiled to WebAssembly.

Expand Down Expand Up @@ -76,30 +78,40 @@ success.
```ts
import { diffBytes, patchBytes } from 'react-native-bs-diff-patch';

export async function webRoundTrip(oldFile: File, newFile: File) {
export async function webRoundTrip(
oldFile: File,
newFile: File,
signal?: AbortSignal
) {
const oldData = await oldFile.arrayBuffer();
const newData = await newFile.arrayBuffer();
const patchData = await diffBytes(oldData, newData);
const restoredData = await patchBytes(oldData, patchData);
const options = {
signal,
maxInputBytes: 64 * 1024 * 1024,
maxOutputBytes: 64 * 1024 * 1024,
};
const patchData = await diffBytes(oldData, newData, options);
const restoredData = await patchBytes(oldData, patchData, options);

return { patchData, restoredData };
}
```

`diffBytes` and `patchBytes` accept `ArrayBuffer`, any `ArrayBufferView`
(including typed arrays and `DataView`), or `Blob`. They resolve to a new
`Uint8Array` and leave the caller's buffers usable.
`Uint8Array` and leave the caller's buffers usable. Aborted operations reject
with `EABORTED`; configured size limits reject with `ERESOURCE`.

## Platform API matrix

| API | Android | iOS | Web |
| --------------------------------------- | ------- | --- | --- |
| `diff(oldPath, newPath, patchPath)` | Yes | Yes | No |
| `patch(oldPath, outputPath, patchPath)` | Yes | Yes | No |
| `diffBytes(oldData, newData)` | No | No | Yes |
| `patchBytes(oldData, patchData)` | No | No | Yes |
| Legacy architecture | Yes | Yes | N/A |
| New Architecture / TurboModule | Yes | Yes | N/A |
| API | Android | iOS | Web |
| ------------------------------------------ | ------- | --- | --- |
| `diff(oldPath, newPath, patchPath)` | Yes | Yes | No |
| `patch(oldPath, outputPath, patchPath)` | Yes | Yes | No |
| `diffBytes(oldData, newData, options?)` | No | No | Yes |
| `patchBytes(oldData, patchData, options?)` | No | No | Yes |
| Legacy architecture | Yes | Yes | N/A |
| New Architecture / TurboModule | Yes | Yes | N/A |

Calling an API family that is unavailable on the current platform rejects with
`EUNSUPPORTED` instead of silently choosing different behavior.
Expand All @@ -117,6 +129,11 @@ Calling an API family that is unavailable on the current platform rejects with
See [Production recipes](./docs/recipes.md) for error handling, downloads,
cross-runtime patch exchange, and integrity checks.

CI directly compiles the Android New Architecture sources against React Native
0.73.11, 0.74.7, and 0.86.0. Packed-consumer tests also verify that browser,
ESM, CommonJS, and TypeScript resolution work without installing optional React
Native peers for Web-only consumers.

## Documentation

- [Getting started](./docs/getting-started.md)
Expand All @@ -130,7 +147,8 @@ cross-runtime patch exchange, and integrity checks.
## Contributing

See [CONTRIBUTING.md](./CONTRIBUTING.md) for the local workflow and quality
gates.
gates. Release history is in [CHANGELOG.md](./CHANGELOG.md); security reports
follow [SECURITY.md](./SECURITY.md).

## License

Expand Down
Loading