napi-rs

Stake to support us chat

This project was initialized from xray

A minimal library for building compiled Node.js add-ons in Rust.

Ecosystem

Prisma     swc     Parcel   next.js   nextjs.svg

Platform Support

Lint Linux musl macOS/Windows/Linux x64 Linux-aarch64 Linux-armv7 macOS-Android Android-armv7 Windows i686 Windows arm64 FreeBSD

MSRV

Rust 1.57.0

| | node12 | node14 | node16 | node18 | | --------------------- | ------ | ------ | ------ | ------ | | Windows x64 | ✓ | ✓ | ✓ | ✓ | | Windows x86 | ✓ | ✓ | ✓ | ✓ | | Windows arm64 | ✓ | ✓ | ✓ | ✓ | | macOS x64 | ✓ | ✓ | ✓ | ✓ | | macOS aarch64 | ✓ | ✓ | ✓ | ✓ | | Linux x64 gnu | ✓ | ✓ | ✓ | ✓ | | Linux x64 musl | ✓ | ✓ | ✓ | ✓ | | Linux aarch64 gnu | ✓ | ✓ | ✓ | ✓ | | Linux aarch64 musl | ✓ | ✓ | ✓ | ✓ | | Linux arm gnueabihf | ✓ | ✓ | ✓ | ✓ | | Linux aarch64 android | ✓ | ✓ | ✓ | ✓ | | Linux armv7 android | ✓ | ✓ | ✓ | ✓ | | FreeBSD x64 | ✓ | ✓ | ✓ | ✓ |

This library depends on Node-API and requires Node@10.0.0 or later.

We already have some packages written by napi-rs: node-rs

One nice feature is that this crate allows you to build add-ons purely with the Rust/JavaScript toolchain and without involving node-gyp.

Taste

You can start from package-template to play with napi-rs

Define JavaScript functions

```rust /// import the preludes use napi::bindgenprelude::*; use napiderive::napi;

/// module registration is done by the runtime, no need to explicitly do it now.

[napi]

fn fibonacci(n: u32) -> u32 { match n { 1 | 2 => 1, _ => fibonacci(n - 1) + fibonacci(n - 2), } }

/// use Fn, FnMut or FnOnce traits to defined JavaScript callbacks /// the return type of callbacks can only be Result.

[napi]

fn getcwd Result<()>>(callback: T) { callback(env::currentdir().unwrap().tostringlossy().to_string()).unwrap(); }

/// or, define the callback signature in where clause

[napi]

fn test_callback(callback: T) where T: Fn(String) -> Result<()> {}

/// async fn, require async feature enabled. /// [dependencies] /// napi = {version="2", features=["async"]}

[napi]

async fn readfileasync(path: String) -> Result { tokio::fs::read(path) .map(|r| match r { Ok(content) => Ok(content.into()), Err(e) => Err(Error::new( Status::GenericFailure, format!("failed to read file, {}", e), )), }) .await } ```

more examples at examples

Building

This repository is a Cargo crate. Any napi-based add-on should contain Cargo.toml to make it a Cargo crate.

In your Cargo.toml you need to set the crate-type to "cdylib" so that cargo builds a C-style shared library that can be dynamically loaded by the Node executable. You'll also need to add this crate as a dependency.

```toml [package] name = "awesome"

[lib] crate-type = ["cdylib"]

[dependencies] napi = "2" napi-derive = "2"

[build-dependencies] napi-build = "1" ```

And create build.rs in your own project:

```rust // build.rs extern crate napi_build;

fn main() { napi_build::setup(); } ```

So far, the napi build script has only been tested on macOS Linux Windows x64 MSVC and FreeBSD.

Install the @napi-rs/cli to help you build your Rust codes and copy Dynamic lib file to .node file in case you can require it in your program.

js { "package": "awesome-package", "devDependencies": { "@napi-rs/cli": "^1.0.0" }, "napi": { "name": "jarvis" // <----------- Config the name of native addon, or the napi command will use the name of `Cargo.toml` for the binary file name. }, "scripts": { "build": "napi build --release", "build:debug": "napi build" } }

Then you can require your native binding:

js require('./jarvis.node')

The module_name would be your package name in your Cargo.toml.

xxx => ./xxx.node

xxx-yyy => ./xxx_yyy.node

You can also copy Dynamic lib file to an appointed location:

bash napi build [--release] ./dll napi build [--release] ./artifacts

There are documents which contains more details about the @napi-rs/cli usage.

Testing

Because libraries that depend on this crate must be loaded into a Node executable in order to resolve symbols, all tests are written in JavaScript in the test_module subdirectory.

To run tests:

sh yarn build:test yarn test

Related projects

Features table

| Rust Type | Node Type | NAPI Version | Minimal Node version | Enable by napi feature | | ------------------------ | ------------------- | ------------------------------------------------------------------------------- | -------------------- | ------------------------ | | u32 | Number | 1 | v8.0.0 | | i32/i64 | Number | 1 | v8.0.0 | | f64 | Number | 1 | v8.0.0 | | bool | Boolean | 1 | v8.0.0 | | String/&'a str | String | 1 | v8.0.0 | | Latin1String | String | 1 | v8.0.0 | latin1 | | UTF16String | String | 1 | v8.0.0 | | Object | Object | 1 | v8.0.0 | | serdejson::Map | Object | 1 | v8.0.0 | serde-json | | serdejson::Value | any | 1 | v8.0.0 | serde-json | | Array | Array | 1 | v8.0.0 | | Vec | Array | 1 | v8.0.0 | | Buffer | Buffer | 1 | v8.0.0 | | External | External | 1 | v8.0.0 | | | Null | null | 1 | v8.0.0 | | Undefined/() | undefined | 1 | v8.0.0 | | Result<()> | Error | 1 | v8.0.0 | | T: Fn(...) -> Result | Function | 1 | v8.0.0 | | Async/Future | Promise | 4 | v10.6.0 | async | | AsyncTask | Promise | 1 | v8.5.0 | | JsGlobal | global | 1 | v8.0.0 | | JsSymbol | Symbol | 1 | v8.0.0 | | Int8Array/Uint8Array ... | TypedArray | 1 | v8.0.0 | | JsFunction | threadsafe function | 4 | v10.6.0 | napi4 | | BigInt | BigInt | 6 | v10.7.0 | napi6 |