Thank you for your interest in contributing to react-native-rs! This guide will help you get started.
-
Clone the repository:
git clone https://github.com/Axnjr/react-native-rs cd react-native-rs -
Install dependencies:
yarn install
-
Set up Rust environment:
yarn setup-rust
-
Build the project:
yarn build-all
react-native-rs/
├── src/ # TypeScript bridge code
├── rust/ # Rust implementation
│ ├── src/
│ │ ├── commands/ # Individual command implementations
│ │ ├── lib.rs # Main library entry point
│ │ └── cmd.rs # Command definitions
│ ├── build.sh # Cross-platform build script
│ └── Cargo.toml # Rust dependencies
├── ios/ # iOS native module
├── android/ # Android native module
├── cpp/ # C++ bridge layer
└── example/ # Example React Native app
To add a new command to the bridge:
-
Create a new command module in Rust:
// rust/src/commands/my_command.rs use serde::{Deserialize, Serialize}; use eyre::Result; #[cfg(feature = "ts-rs")] use ts_rs::TS; #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export))] pub struct MyCommandInput { pub value: i32, } #[derive(Debug, Serialize, Deserialize)] #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export))] pub struct MyCommandResult { pub result: i32, } pub async fn my_command(input: &MyCommandInput) -> Result<MyCommandResult> { // Your implementation here Ok(MyCommandResult { result: input.value * 2, }) }
-
Add to the command enum:
// rust/src/cmd.rs #[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "ts-rs", derive(TS))] #[cfg_attr(feature = "ts-rs", ts(export))] #[serde(tag = "cmd", content = "params", rename_all = "snake_case")] pub enum Command { // ... existing commands MyCommand(MyCommandInput), }
-
Add to the executor:
// rust/src/cmd.rs pub async fn execute_cmd(cmd: Arc<Command>, logs: &'static Mutex<Vec<String>>) -> Result<String, eyre::Error> { match &*cmd { // ... existing cases Command::MyCommand(input) => parse_result(my_command(input).await?), } }
-
Generate TypeScript types:
yarn generate-types
-
Use in React Native:
const result = await RustBridge.execute({ cmd: 'my_command', params: { value: 42 } });
cd rust
cargo testyarn testyarn example:ios
# or
yarn example:android- Rust: Follow standard Rust formatting with
cargo fmt - TypeScript: We use Prettier for formatting
- Commit Messages: Use conventional commit format
- Use appropriate algorithms: Choose the right algorithm for the task
- Leverage parallelism: Use
rayonfor CPU-intensive tasks when beneficial - Memory management: Be mindful of memory allocations in hot paths
- Error handling: Use
eyrefor comprehensive error context
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Make your changes
- Add tests for new functionality
- Run the test suite:
yarn test && cd rust && cargo test - Generate types:
yarn generate-types - Commit your changes:
git commit -m "feat: add my feature" - Push to your fork:
git push origin feature/my-feature - Create a Pull Request
- Description: Clearly describe what your PR does and why
- Tests: Include tests for new functionality
- Documentation: Update documentation if needed
- Types: Ensure TypeScript types are generated and committed
- Breaking Changes: Clearly mark any breaking changes
- Update version in
package.jsonandrust/Cargo.toml - Update
CHANGELOG.md - Generate and commit TypeScript types
- Create a release PR
- After merge, tag the release:
git tag v0.x.x - Push tags:
git push --tags - Publish to npm:
npm publish
- Issues: Open an issue for bugs or feature requests
- Discussions: Use GitHub Discussions for questions
- Discord: Join our Discord server for real-time help
This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code.
Thank you for contributing! 🚀