Skip to content
 
 

Latest commit

 

History

3,715 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

chat

Sponsors

Platform Support

Test & Release Address Sanitizer Memory Leak Detect

MSRV

Rust 1.88.0

node12 node14 node16 node18 node20 node22
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 gnu N/A N/A N/A ✓ ✓ ✓
Linux riscv64 gnu N/A N/A ✓ ✓ ✓ ✓
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

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.

[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:

// 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 @napi-rs/cli as a local development dependency to build the Rust crate and copy its dynamic library to a loadable .node file.

{
  "name": "awesome-package",
  "devDependencies": {
    "@napi-rs/cli": "^3.0.0"
  },
  "napi": {
    "binaryName": "jarvis"
  },
  "scripts": {
    "build": "napi build --release",
    "build:debug": "napi build"
  }
}

Then you can require your native binding:

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:

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:

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
OsString/&'a OsStr String 1 v8.0.0
PathBuf/&'a Path String 1 v8.0.0
Latin1String String 1 v8.0.0 latin1
UTF16String String 1 v8.0.0
Object Object 1 v8.0.0
serde_json::Map Object 1 v8.0.0 serde-json
serde_json::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

About

A framework for building compiled Node.js add-ons in Rust via Node-API

Resources

Code of conduct

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages