No description
Find a file
forehalo 2467b7139b
Introduce #[napi] procedural macro to automation development boilerplate (#696)
* napi procedural macro for basic rust/JavaScript types
* introduce the `compat-mode` for `napi` and `napi-derive` crates for backward compatible
* remove #[inline] and let compiler to decide the inline behavior
* cli now can produce the `.d.ts` file for native binding
* many tests and example for the new procedural macro

Co-authored-by: LongYinan <lynweklm@gmail.com>
2021-09-23 01:29:09 +08:00
.github Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
.husky chore: upgrade deps 2021-03-11 13:42:28 +08:00
bench Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
cli Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
crates Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
examples Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
images docs: add next.js into README 2021-07-30 13:14:54 +08:00
memory-testing Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
triples chore: publish 2021-07-22 13:51:40 +08:00
.cirrus.yml ci: fix FreeBSD 2021-05-27 22:41:31 +08:00
.dockerignore feat(napi): support musl linux 2020-06-11 16:20:37 +08:00
.editorconfig init 2018-04-28 16:26:38 +08:00
.eslintignore chore: reduce published size 2021-07-22 13:35:01 +08:00
.eslintrc.yml Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
.gitignore docs: add discord badge 2021-08-09 22:18:48 +08:00
.npmignore feat: support linux aarch64 2020-10-15 09:12:43 +08:00
.prettierignore chore: reduce published size 2021-07-22 13:35:01 +08:00
.yarnrc feat: upgrade to std-future 2020-02-18 21:09:17 +08:00
alpine.Dockerfile ci: add musl-cross toolchains into alpine.Dockerfile 2021-07-22 00:01:50 +08:00
ava.config.js Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
Cargo.toml Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
CODE_OF_CONDUCT.md doc: add email to CODE_OF_CONDUCT 2020-05-20 18:49:36 +08:00
debian.Dockerfile build: add aarch64-linux-gnu toolchain in Docker image 2021-07-20 14:32:34 +08:00
generate-triple-list.ts feat(cli): upgrade clipanion v3 2021-08-07 00:23:17 +08:00
lerna.json @napi-rs/cli@1.0.0-alpha.12 2020-12-23 22:46:48 +08:00
LICENSE docs: update license 2021-01-25 14:12:44 +08:00
package.json Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
README.md Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00
rustfmt.toml Allow dropping of string&buffer values when converting 2021-05-27 20:47:22 +02:00
tsconfig.json feat(cli): upgrade clipanion v3 2021-08-07 00:23:17 +08:00
tsconfig.root-lint.json ci: add memory leak detect job 2021-05-29 23:24:25 +08:00
yarn.lock Introduce #[napi] procedural macro to automation development boilerplate (#696) 2021-09-23 01:29:09 +08:00

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 N-API@3 Linux musl macOS/Windows/Linux x64 Linux-aarch64 Linux-armv7 macOS-Android Windows i686 Windows arm64 FreeBSD

node12 node14 node16
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
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

#[macro_use]
extern crate napi;

// import the preludes
use napi::bindgen_prelude::*;

/// module registerion is done by the runtime, no need to explicitly do it now.
#[napi]
fn fibonacci(n: u32) -> u32 {
  match n {
    1 | 2 => 1,
    _ => fibonacci_native(n - 1) + fibonacci_native(n - 2),
  }
}

/// use `Fn`, `FnMut` or `FnOnce` traits to defined JavaScript callbacks
/// the return type of callbacks can only be `Result`.
#[napi]
fn get_cwd<T: Fn(String) -> Result<()>>(callback: T) {
  callback(env::current_dir().unwrap().to_string_lossy().to_string()).unwrap();
}

/// or, define the callback signature in where clause
#[napi]
fn test_callback<T>(callback: T)
where T: Fn(String) -> Result<()>
{}

Checkout more examples in examples folder

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

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

{
  "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:

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

Features table

Rust Type Node Type NAPI Version Minimal Node version
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
UTF16String String 1 v8.0.0
Object Object 1 v8.0.0
Array Array 1 v8.0.0
Vec Array 1 v8.0.0
Buffer Buffer 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
(NOT YET) global 1 v8.0.0
(NOT YET) Symbol 1 v8.0.0
(NOT YET) Promise 1 b8.5.0
(NOT YET) ArrayBuffer/TypedArray 1 v8.0.0
(NOT YET) threadsafe function 4 v10.6.0
(NOT YET) BigInt 6 v10.7.0