Generate and build Node-API bindings for MoonBit.
| Capability | Description |
|---|---|
| 🎯 Zero-Boilerplate Exports | Export pub fn and pub async fn with #export_name("..."), alongside owned pub struct and pub enum value types. Native classes are configured cleanly in napi-mbt.json. |
| 🛡️ Strict Boundary Validation | Rejects NaN, ±Infinity, fractional floats passed to integers, out-of-range 32-bit/64-bit numbers, and invalid UTF-16/Buffer inputs at the C boundary before entering MoonBit. |
| ⚡ Full Async & Concurrency Stack | Supports cancellable pub async fn Promises (moonbitlang/async@0.22.4 + libuv with AbortSignal), native C worker pool tasks (nativeTasks), isolated MoonBit worker process pools (workerTasks), awaited JS Promises (NapiJsPromise), and demand-driven async streams (NapiAsyncIterator). |
| 🧱 Safe Classes & Callbacks | Native classes include constructors, static factories, getters/setters, methods, and explicit idempotent .dispose(). Callbacks support typed MoonBit signatures (Args) -> Ret raise, returned closures with .dispose(), and threadsafe functions (NapiCallback). |
| 🔒 Isolated, Cached Builds | Compiles inside isolated workspaces without mutating user source files. Includes content-addressed build caching, watch mode (--watch), and native symbol collision inspection (nm / dumpbin). |
| 📦 Precise ABI & Engine Ranges | Targets N-API v4 by default and automatically raises the required N-API level (up to v8) only when higher-level features are used, computing the exact engines.node intersection in package.json. |
| OS | Architecture | C Runtime / Toolchain | Package Platform Triple |
|---|---|---|---|
| Windows | x64 | MSVC (cl / MSBuild + Windows SDK) | win32-x64-msvc |
| Linux | x64, arm64 | glibc (gcc / clang) | linux-x64-gnu, linux-arm64-gnu |
| Linux | x64, arm64 | musl (Alpine native toolchain) | linux-x64-musl, linux-arm64-musl |
| macOS | x64, arm64 | Apple Clang (Xcode / Command Line Tools) | darwin-x64, darwin-arm64 |
[!NOTE] Cross-architecture compilation is intentionally rejected unless running on a matching host toolchain. On Linux (gnu and musl), compiler probes and output ELF dynamic dependencies (PT_INTERP / DT_NEEDED) are verified before installing .node binaries and again during prepublish. See Support Policy and Platform Validation.
| Feature Surface | Minimum N-API | Minimum Node.js Consumer Baseline |
|---|---|---|
| Scalars (Int, UInt, Double, Bool), UTF-16 String, owned struct / enum / Array / Map | 1 | Node 10.16.0 (CJS) / 12.20.0 (Dual CJS+ESM) |
| Native classes (NapiClass) & callback lifecycle | 3 | Node 10.16.0 (CJS) / 12.20.0 (Dual CJS+ESM) |
| Stored / threadsafe callbacks (NapiCallback, default CLI target) | 4 | >=12.20.0 <13 \|\| >=14.13.1 (Dual default) |
| Exact 64-bit Int64 / UInt64 (bigint) | 6 | Node 10.7.0+ (intersected with loader mode) |
| Bytes (Buffer) & synchronous borrowed NapiBufferView | 7 | Node 10.16.0+ (intersected with loader mode) |
| pub async fn, NapiTask, NapiJsPromise, NapiAsyncIterator, async host cleanup | 8 | >=12.22.0 <13 \|\| >=14.17.0 <15 \|\| >=15.12.0 <16 \|\| >=16.0.0 |
| Web ReadableStream helper (*Stream) | 8 | Node 18.0.0+ |
moon install unmbt/napi-mbt/cmd/napi-mbt-clinapi-mbt-cli doctornapi-mbt-cli init my-addon
cd my-addon
moon update
moon check
napi-mbt-cli build///|
pub(all) struct Summary {
label : String
total : Int
}
///|
#export_name("summarize")
pub fn summarize(label : String, values : Array[Int]) -> Summary raise {
if label.is_empty() {
fail("label must not be empty")
}
let mut total = 0
for v in values {
total += v
}
{ label, total }
}import { summarize } from './index.mjs';
// or: const { summarize } = require('./index.cjs');
console.log(summarize('orders', [10, 20, 30]));
// => { label: 'orders', total: 60 }| MoonBit Type | JavaScript / TypeScript | Semantics & Boundary Guarantees |
|---|---|---|
| Int, UInt | number | Checked 32-bit signed ([-2^31, 2^31 - 1]) and unsigned ([0, 2^32 - 1]) integers; rejects NaN, ±Infinity, and fractions. |
| Int64, UInt64 | bigint | Checked 64-bit signed/unsigned BigInt (N-API 6); rejects out-of-range 64-bit values. |
| Double, Float, Bool, Unit | number, boolean, void | Preserves IEEE-754 values, including NaN and ±Infinity. |
| String | string | Direct UTF-16 string conversion without intermediate UTF-8 transcoding. |
| Bytes | Buffer | Owned byte copy across the boundary (N-API 7); safe to store and return from async functions. |
| NapiBufferView | Buffer | Zero-copy synchronous borrow (N-API 7); valid only during the synchronous call frame. |
| NapiUint8Array / NapiInt32Array / NapiUint32Array / NapiFloat32Array / NapiFloat64Array / NapiArrayBuffer | Uint8Array / Int32Array / Uint32Array / Float32Array / Float64Array / ArrayBuffer | Owned typed-array and ArrayBuffer copies with full element length preservation. |
| T?, Array[T], Map[String, T], (A, B, ...), Json | T \| null, Array<T>, Record<string, T>, [A, B, ...], JsonValue | Recursive structural validation; Option::None maps to null (and accepts null or undefined on input). |
| pub struct / pub enum | Object / Discriminated Union | Exported structs map to typed JS objects; enums map to variant name string or { tag: "Variant", args: [...] } discriminated unions. |
| Configured Class (napi-mbt.json) | class with dispose() | Native handle wrapping with constructors, static factories, properties, methods, and deterministic disposal. |
| (Args) -> Ret raise / NapiCallback | (...args) => Ret | Supports synchronous call-scoped invocations, returned closures with dispose(), and threadsafe functions (N-API 4). |
| pub async fn(...) -> T | Promise<T> (with { signal?: AbortSignal }) | Runs on the embedded moonbitlang/async@0.22.4 + libuv loop (N-API 8) with cooperative cancellation. |
| NapiJsPromise[T] | Promise<T> | Awaits JavaScript Promises inside MoonBit async fn exports with typed resolution. |
| NapiAsyncIterator[T] | AsyncIterableIterator<T> & ReadableStream<T> | Demand-driven streaming input/output with backpressure and early consumer cancellation (return()). |
| nativeTasks / workerTasks (napi-mbt.json) | Promise<T> / Worker Pool | Offloads C jobs to the libuv threadpool (nativeTasks) or pure MoonBit jobs to isolated Node worker process pools (workerTasks). |
napi-mbt-cli <command> [directory] [options]| Command | Description |
|---|---|
| init <dir> | Create the official addon template (--name <name>, --force). |
| generate [dir] | Generate bindings and loaders (--check to validate without writing files). |
| build [dir] | Build the native addon in isolation (--release, --watch, --no-cache, --dry-run, --verbose, --target <t>, --output-dir <p>). |
| clean [dir] | Remove this project's persistent build cache (--cache). |
| doctor [dir] | Check the native compiler, linker, and platform SDK (--json). |
| prepublish [dir] | Validate release artifacts and prepare npm platform package metadata (--target <t>). |
| targets | List supported host target profiles. |
| Topic | Guide |
|---|---|
| Getting Started & CLI Usage | Usage Guide · Build & Loader Pipeline |
| Platform & ABI Policy | Support Policy · Platform Validation · Validation Record |
| Type System & Objects | Type Mapping · Classes & Callbacks · Threadsafe Functions |
| Async, Streams & Workers | Async Functions · Async Adapter · JS Promises · Async Streams · Native Tasks · Worker Pools |
| Engineering & Benchmarks | Performance Benchmarks · Development Workflow · Roadmap |
| Example | Demonstrated Capabilities |
|---|---|
| examples/hello-addon | Dual CJS/ESM imports and strict scalar boundary checks |
| examples/structured-data | Nested struct / enum records, Option, Array, Map, and Json |
| examples/native-class | Stateful class handles configured in napi-mbt.json, getters/setters, static factories, and .dispose() |
| examples/callbacks | Synchronous callbacks, stored threadsafe functions, and JS exception propagation |
| examples/async-file | pub async fn native file I/O, AbortSignal cancellation, and error recovery |
| examples/binary-processing | Owned Bytes (Buffer) vs. zero-copy synchronous NapiBufferView and TypedArrays |
| examples/native-tasks | C worker-pool jobs (nativeTasks), cancellation, and composition with MoonBit async fn |
| examples/worker-tasks | Pure MoonBit CPU-bound computation in isolated Node worker process pools (workerTasks) |
| examples/streams | NapiAsyncIterator input/output, backpressure, cancellation, and Web ReadableStream |
moon run examples/setup.mbtx examples/hello-addon ../my-hello-addon
cd ../my-hello-addon
pnpm testmoon run scripts/toolchain-check.mbtx # Verify pinned MoonBit, CMake, and host toolchain
moon check # Typecheck all MoonBit packages
moon test # Run unit, whitebox, and blackbox tests
moon run scripts/docs-check.mbtx # Verify Markdown links and documentation gates
moon run scripts/release-check.mbtx # Verify module version and lockfile hygiene
moon run scripts/examples-test.mbtx # Package the CLI and build/test all 9 standalone examples| Component | Version / Source | Usage in napi-mbt | License | Repository / Archive License Path |
|---|---|---|---|---|
| Tree-sitter C Runtime | v0.26.8 (cd5b087c) · tree-sitter/tree-sitter | Vendored C parser runtime for MoonBit AST analysis | MIT | internal/syntax/vendor/TREE-SITTER-LICENSE (licenses/TREE-SITTER-LICENSE) |
| Unicode Character Database | Unicode Consortium (bundled in Tree-sitter) | Unicode character tables in Tree-sitter lexer | Unicode-DFS-2016 | internal/syntax/vendor/runtime/unicode/LICENSE (licenses/UNICODE-LICENSE) |
| Tree-sitter MoonBit Grammar | Commit 190881df (ABI 15) · unmbt/tree-sitter-moonbit | Vendored MoonBit grammar tables (parser.c / scanner.c) | Apache-2.0 AND MIT | internal/syntax/vendor/GRAMMAR-LICENSE (licenses/GRAMMAR-LICENSE) |
| Node-API Headers (node-api-headers) | v1.9.0 · nodejs/node-api-headers | Embedded node_api.h & js_native_api.h headers for standalone builds | MIT | Embedded in internal/assets/data/resources.json (licenses/NODE-API-LICENSE) |
| MoonBit Async Runtime (moonbitlang/async) | v0.22.4 · moonbitlang/async | Embedded native async event-loop bridge and runtime support | Apache-2.0 | Embedded in internal/assets/data/resources.json (licenses/MOONBIT-ASYNC-LICENSE) |
| libuv Headers & Declarations | libuv/libuv | Embedded libuv declarations for Node.js event-loop integration | MIT | Embedded in internal/assets/data/resources.json (licenses/LIBUV-LICENSE) |
pub(all) suberror NapiError {
JavaScriptException(NapiReference)
ApiError(status~ : Int, kind~ : NapiErrorKind, code~ : String, context~ : String)
}#external
pub type NapiArgumentsfn NapiArguments::get(self : NapiArguments, env : NapiEnv, index : Int) -> NapiValue raise NapiErrorpub struct NapiArrayBuffer {
// private fields
}pub type NapiCallbackpub struct NapiFloat32Array {
// private fields
}pub struct NapiFloat64Array {
// private fields
}pub struct NapiInt32Array {
// private fields
}pub type NapiReferencepub struct NapiUint32Array {
// private fields
}pub struct NapiUint8Array {
// private fields
}fn napi_class_handle(env : NapiEnv, value : NapiValue, type_id : Int) -> UnmanagedBuffer raise NapiErrorfn napi_promise_reject(env : NapiEnv, promise : NapiPromise, reason : NapiValue) -> Unit raise NapiErrorfn napi_promise_resolve(env : NapiEnv, promise : NapiPromise, value : NapiValue) -> Unit raise NapiErrorfn napi_threadsafe_function_acquire(func : NapiThreadsafeFunction) -> NapiTsfnStatus raise NapiErrorfn napi_threadsafe_function_call(func : NapiThreadsafeFunction, data : UnmanagedBuffer, mode : NapiTsfnCallMode) -> NapiTsfnStatus raise NapiErrorfn napi_threadsafe_function_create(env : NapiEnv, func : NapiValue, async_resource : NapiValue, async_resource_name : NapiValue, max_queue_size : Int, initial_thread_count : Int, finalize_data : UnmanagedBuffer, finalize_cb : UnmanagedBuffer, context : UnmanagedBuffer, call_js_cb : UnmanagedBuffer) -> NapiThreadsafeFunction raise NapiErrorfn napi_threadsafe_function_release(func : NapiThreadsafeFunction, mode : NapiTsfnReleaseMode) -> NapiTsfnStatus raise NapiError