Sign in

    napi-mbt

    Generate and build Node-API bindings for MoonBit.

    Download zip
    Author
    Version
    0.1.1
    License
    MIT
    Last updated
    10 hours ago
    Downloads
    3

    Dependencies


    #🌟 Introduction

    napi-mbt is a framework inspired by napi-rs that empowers developers to build native Node.js addons using MoonBit, a fast and lightweight multi-paradigm language. napi-mbt bridges MoonBit and Node.js with a zero-overhead Node-API (N-API) C ABI, avoiding the memory cost of WASM-based marshaling while maintaining optimal execution performance.

    The repository publishes a native MoonBit CLI to Mooncakes and GitHub Releases. The Node CLI remains a fallback transport for tree-sitter generation, while the native launcher makes global npm installation optional.

    #✨ Key Features

    • ⚡ Zero Overhead Native ABI: napi-mbt natively connects MoonBit with Node-API without WASM intermediaries, guaranteeing bare-metal execution performance.
    • đŸĒ„ #export_name generation: The annotation name becomes the C ABI, JavaScript, and TypeScript export name;
    • 📝 Automatic TypeScript Typing: Generates .d.ts declaration files effortlessly alongside your MoonBit compilations for strong-typed JS/TS consumption.
    • 🚀 Zero-Copy Buffer Mutation: Safely manipulate Node.js Buffers directly in MoonBit memory using NapiBufferView.
    • đŸ“Ļ Integrated Cross-Platform CI/CD: Builds native modules and CLI binaries for Windows x64, Linux x64, and macOS ARM64. Platform packages use NPM's optionalDependencies pattern.

    Intel macOS prebuilt releases are paused because the current MoonBit toolchain installer does not support macOS x64. macOS CI and GitHub Releases target Apple Silicon (ARM64). Existing Intel package metadata is retained for compatibility.

    #🚀 Quick Start

    #1. Requirements

    • đŸŸĸ Node.js >= 8.6
    • 🌙 MoonBit Toolchain
    • 🔨 A C Compiler (GCC/Clang on Unix, MSVC on Windows)

    #Installing the CLI

    Use moon install (recommended, once a release containing this entry point is on Mooncakes):

    moon install unmbt/napi-mbt/cmd/napi-mbt-cli napi-mbt-cli --help

    This installs napi-mbt-cli (napi-mbt-cli.exe on Windows) into ~/.moon/bin. Ensure that directory is on PATH. To install the current checkout before a new Mooncakes release, or choose ~/.unmbt as the destination:

    moon install ./cmd/napi-mbt-cli moon install ./cmd/napi-mbt-cli --bin ~/.unmbt

    You can also build from source:

    moon build --target native --release cmd/napi-mbt-cli

    The native CLI uses moonbitlang/core/argparse for subcommands and help. Its version comes from moon.mod: the gen_version rule and dev_build in cmd/napi-mbt-cli/moon.pkg run scripts/gen_version.mbtx to regenerate generated_version.mbt. Keep that generated file in releases for downstream builds. Run moon run scripts/cli-native-test.mbtx to check argument handling and version regeneration.

    Or install the precompiled native CLI into ~/.unmbt (Windows uses %USERPROFILE%\.unmbt):

    On Unix-like systems the repository installer performs the same version check:

    curl -fsSL https://raw.githubusercontent.com/unmbt/napi-mbt/master/scripts/install.sh | bash

    On Windows PowerShell:

    irm https://raw.githubusercontent.com/unmbt/napi-mbt/master/scripts/install.ps1 | iex

    moon install installs the native executable only. init, generate, build and prepublish currently require Node.js and the Node fallback. Install @unmbt/napi-mbt-cli as a project dev dependency (searched in the current directory and its parents), or set NAPI_MBT_NODE_RUNTIME to an absolute path to cli/bin/napi-mbt.js in a checkout with its npm dependencies installed. The GitHub Release installer bundles the fallback and its dependencies. Help, version queries and targets run entirely in MoonBit.

    #2. Project Setup

    Create a new Node.js project (the native CLI is already on your PATH):

    mkdir my-napi-addon cd my-napi-addon npm init -y npm install --save-dev @unmbt/napi-mbt-cli npm install node-api-headers

    Initialize your MoonBit package and configure moon.pkg:
    moon new lib

    #3. Writing MoonBit Code

    In your lib.mbt, write a function and tag it with #export_name("mbt_add"):

    #export_name("mbt_add")
    pub fn add(a : Int, b : Int) -> Int {
    a + b
    }

    #4. Build the Addon

    Run the CLI tool to auto-generate bindings and build the .node binary:

    napi-mbt-cli build

    This command will:
    1. 🔍 Parse your #export_name("mbt_add") annotated functions.
    2. đŸ› ī¸ Generate napi_exports.mbt and index.d.ts.
    3. đŸ—ī¸ Compile the Native target (moon build --target native).
    4. đŸ“Ļ Generate .node binary at artifacts/[platform]-[arch]/.

    You can now use your native addon in JavaScript:

    const addon = require('./artifacts/win32-x64-msvc/napi_mbt.node'); console.log(addon.mbt_add(2, 3)); // Output: 5

    Set one package-wide N-API version in napi-mbt.json. The default v1 covers Node 8.6–26; Threadsafe Function requires v4 and BigInt requires v6. Core Promise APIs are v1 according to the Node-API headers.

    #Release and publish

    Version releases use the repository's bump.config.json; it runs moon check before the version is committed. After all target binaries have been built, prepare platform packages and publish them in dependency order:

    npm run publish:prepare npm run publish:all

    Use npm run publish:dry-run to inspect package contents without publishing.

    #📚 Documentation

    For a detailed guide on supported types, advanced configurations, and internal architectures, refer to the documentation directories:

    #📄 License

    This project is licensed under the MIT License. See the LICENSE file for details.

    NapiBufferView

    pub struct NapiBufferView {
    buf : UnmanagedBuffer
    len : Int
    is_alive : Bool
    }

    NapiBufferView::invalidate

    fn NapiBufferView::invalidate(self : NapiBufferView) -> Unit

    Invalidates a borrowed Buffer view after the callback returns.

    NapiBufferView::length

    fn NapiBufferView::length(self : NapiBufferView) -> Int

    NapiBufferView::load8

    fn NapiBufferView::load8(self : NapiBufferView, offset : Int) -> Int

    NapiBufferView::store8

    fn NapiBufferView::store8(self : NapiBufferView, offset : Int, val : Int) -> Unit

    NapiCallbackInfo

    #external
    pub type NapiCallbackInfo

    NapiDeferred

    #external
    pub type NapiDeferred

    NapiEnv

    #external
    pub type NapiEnv

    NapiPromise

    pub struct NapiPromise {
    promise : NapiValue
    deferred : NapiDeferred
    }

    NapiThreadsafeFunction

    #external
    pub type NapiThreadsafeFunction

    NapiValue

    #external
    pub type NapiValue

    UnmanagedBuffer

    #external
    pub type UnmanagedBuffer

    add

    fn add(a : Int, b : Int) -> Int

    check_bool

    fn check_bool(b : Bool) -> Bool

    check_double

    fn check_double(d : Double) -> Double

    concat

    fn concat(a : String, b : String) -> String

    get_Bool

    fn get_Bool(env : NapiEnv, val : NapiValue) -> Bool

    get_Bytes

    fn get_Bytes(env : NapiEnv, val : NapiValue) -> Bytes

    get_Double

    fn get_Double(env : NapiEnv, val : NapiValue) -> Double

    get_Int

    fn get_Int(env : NapiEnv, val : NapiValue) -> Int

    get_NapiBufferView

    fn get_NapiBufferView(env : NapiEnv, val : NapiValue) -> NapiBufferView

    get_String

    fn get_String(env : NapiEnv, val : NapiValue) -> String

    moonbit_release_handle

    fn moonbit_release_handle(id : Int) -> Unit

    mutate_buffer

    fn mutate_buffer(view : NapiBufferView) -> Unit

    napi_bigint_from_int64

    fn napi_bigint_from_int64(env : NapiEnv, value : Int64) -> NapiValue

    napi_bigint_from_uint64

    fn napi_bigint_from_uint64(env : NapiEnv, value : UInt64) -> NapiValue

    napi_bigint_to_int64

    fn napi_bigint_to_int64(env : NapiEnv, value : NapiValue) -> (Int64, Bool)

    Reads a signed BigInt and returns the value plus the lossless flag.

    napi_bigint_to_uint64

    fn napi_bigint_to_uint64(env : NapiEnv, value : NapiValue) -> (UInt64, Bool)

    Reads an unsigned BigInt and returns the value plus the lossless flag.

    napi_mbt_adapter_add

    fn napi_mbt_adapter_add(env : NapiEnv, a0 : NapiValue, a1 : NapiValue) -> NapiValue

    napi_mbt_adapter_check_bool

    fn napi_mbt_adapter_check_bool(env : NapiEnv, a0 : NapiValue) -> NapiValue

    napi_mbt_adapter_check_double

    fn napi_mbt_adapter_check_double(env : NapiEnv, a0 : NapiValue) -> NapiValue

    napi_mbt_adapter_concat

    fn napi_mbt_adapter_concat(env : NapiEnv, a0 : NapiValue, a1 : NapiValue) -> NapiValue

    napi_mbt_adapter_mutate_buffer

    fn napi_mbt_adapter_mutate_buffer(env : NapiEnv, a0 : NapiValue) -> NapiValue

    napi_mbt_adapter_roundtrip_bytes

    fn napi_mbt_adapter_roundtrip_bytes(env : NapiEnv, a0 : NapiValue) -> NapiValue

    napi_promise_is

    fn napi_promise_is(env : NapiEnv, value : NapiValue) -> Bool

    Returns whether a value is a JavaScript Promise.

    napi_promise_new

    fn napi_promise_new(env : NapiEnv) -> NapiPromise

    Promise support is available in Node-API v1.

    napi_promise_reject

    fn napi_promise_reject(env : NapiEnv, promise : NapiPromise, reason : NapiValue) -> Unit

    napi_promise_resolve

    fn napi_promise_resolve(env : NapiEnv, promise : NapiPromise, value : NapiValue) -> Unit

    napi_threadsafe_function_acquire

    fn napi_threadsafe_function_acquire(func : NapiThreadsafeFunction) -> Unit

    napi_threadsafe_function_call

    fn napi_threadsafe_function_call(func : NapiThreadsafeFunction, data : UnmanagedBuffer, mode : Int) -> Unit

    napi_threadsafe_function_create

    fn 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

    Creates a Threadsafe Function. Callback pointers are opaque unmanaged pointers supplied by a C layer.

    napi_threadsafe_function_release

    fn napi_threadsafe_function_release(func : NapiThreadsafeFunction, mode : Int) -> Unit

    Threadsafe Function lifecycle helper. Threadsafe Functions require N-API v4.

    registry_get

    fn registry_get(id : Int) -> String?

    registry_release

    fn registry_release(id : Int) -> Unit

    registry_retain

    fn registry_retain(obj : String) -> Int

    roundtrip_bytes

    fn roundtrip_bytes(b : Bytes) -> Bytes

    set_Bool

    fn set_Bool(env : NapiEnv, val : Bool) -> NapiValue

    set_Bytes

    fn set_Bytes(env : NapiEnv, val : Bytes) -> NapiValue

    set_Double

    fn set_Double(env : NapiEnv, val : Double) -> NapiValue

    set_Int

    fn set_Int(env : NapiEnv, val : Int) -> NapiValue

    set_String

    fn set_String(env : NapiEnv, val : String) -> NapiValue

    set_Unit

    fn set_Unit(env : NapiEnv, _val : Unit) -> NapiValue

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    Š 2026 mooncakes.io