Back to Napi Rs

napi-rs

README.md

1.0.010.9 KB
Original Source

napi-rs

This project was initialized from xray

A framework for building compiled Node.js add-ons in Rust via Node-API. Website: https://napi.rs

<p> <a href="https://discord.gg/SpWzYHsKHs"> </a> <a href="https://docs.rs/crate/napi"></img></a> <a href="https://crates.io/crates/napi"></img></a> <a href="https://www.npmjs.com/package/@napi-rs/cli"></img></a> </p>

Sponsors

Platform Support

MSRV

Rust 1.88.0

node12node14node16node18node20node22
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 arm muslebihf
Linux powerpc64le gnu
Linux s390x gnu
Linux loong64 gnuN/AN/AN/A
Linux riscv64 gnuN/AN/A
Linux aarch64 android
Linux armv7 android
FreeBSD x64

This library depends on Node-API and requires [email protected] 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
use napi::bindgen_prelude::*;
use napi_derive::napi;

/// module registration is done by the runtime, no need to explicitly do it now.
#[napi]
pub 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]
pub fn get_cwd<T: Fn(String) -> Result<()>>(callback: T) {
  callback(
    std::env::current_dir()
      .unwrap()
      .to_string_lossy()
      .to_string(),
  )
  .unwrap();
}

/// or, define the callback signature in where clause
#[napi]
pub fn test_callback<T>(callback: T) -> Result<()>
where
  T: Fn(String) -> Result<()>,
{
  callback(std::env::current_dir()?.to_string_lossy().to_string())
}

/// async fn, require `async` feature enabled.
/// [dependencies]
/// napi = {version="2", features=["async"]}
#[napi]
pub async fn read_file_async(path: String) -> Result<Buffer> {
  Ok(tokio::fs::read(path).await?.into())
}

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 = "3"
napi-derive = "3"

[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

Features table

Rust TypeNode TypeNAPI VersionMinimal Node versionEnable by napi feature
u32Number1v8.0.0
i32/i64Number1v8.0.0
f64Number1v8.0.0
boolBoolean1v8.0.0
String/&'a strString1v8.0.0
Latin1StringString1v8.0.0latin1
UTF16StringString1v8.0.0
ObjectObject1v8.0.0
serde_json::MapObject1v8.0.0serde-json
serde_json::Valueany1v8.0.0serde-json
ArrayArray<any>1v8.0.0
Vec<T>Array<T>1v8.0.0
BufferBuffer1v8.0.0
External<T>External<T>1v8.0.0
Nullnull1v8.0.0
Undefined/()undefined1v8.0.0
Result<()>Error1v8.0.0
T: Fn(...) -> Result<T>Function1v8.0.0
Async/FuturePromise<T>4v10.6.0async
AsyncTaskPromise<T>1v8.5.0
JsGlobalglobal1v8.0.0
JsSymbolSymbol1v8.0.0
Int8Array/Uint8Array ...TypedArray1v8.0.0
JsFunctionthreadsafe function4v10.6.0napi4
BigIntBigInt6v10.7.0napi6