OpenHarmony, Node.js, and WebAssembly addons

zig-napi

Build N-API modules with Zig for OpenHarmony, Node.js, and WASI, and generate the matching TypeScript declarations from the same exported surface.

00 · Build pipeline

One root, distinct build targets

Shared root

Zig export root

src/hello.zig

Separate step

TypeScript declarations

napi_build.generateTypeDefinitionindex.d.ts

Declaration generation guide

One Zig root with separately configured build targets. Each guide covers its target's build call, options, and artifacts; declarations are generated from the same root file.

01 · Capability map

One addon surface, multiple outputs

  1. Three runtime outputs

    Use one Zig export surface to build OpenHarmony shared libraries, Node.js addons, and WASI modules in single-threaded or threaded flavors.

  2. Typed JavaScript boundary

    Generate declaration files from functions, classes, enums, async descriptors, structs, and unions.

  3. N-API version gates

    Select Node-API v4 through v10 behavior and fail early when wrappers need a newer runtime API.

  4. Low-level escape hatches

    Work directly with Object, String, Buffer, ArrayBuffer, TypedArray, DataView, External, and references.

02 · Setup

Install as a Zig package

The package exports both the napi module and the napi_build helpers used by examples in this repository.

03 · Build recipes

Copy the shape that matches your target

ZON install

zon
.{
    .name = "appname",
    .version = "0.0.0",
    .minimum_zig_version = "0.17.0",
    .dependencies = .{
        .@"zig-napi" = .{
            .url = "https://github.com/openharmony-zig/zig-napi/archive/refs/tags/<GIT_TAG>.tar.gz",
            .hash = "HASH_GOES_HERE",
        },
    },
}

OpenHarmony

zig
const std = @import("std");
const napi_build = @import("zig-napi").napi_build;

pub fn build(b: *std.Build) !void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const zig_napi = b.dependency("zig-napi", .{});
    const napi = zig_napi.module("napi");

    _ = try napi_build.nativeAddonBuild(b, .{
        .name = "hello",
        .napi_module = napi,
        .root_module_options = .{
            .root_source_file = b.path("./src/hello.zig"),
            .target = target,
            .optimize = optimize,
        },
    });
}

Node addon

zig
const addon = try napi_build.nodeAddonBuild(b, .{
    .name = "hello",
    .napi_module = napi,
    .node_api = .{
        .version = .v8,
        .experimental = false,
    },
    .root_module_options = .{
        .root_source_file = b.path("./src/hello.zig"),
        .target = target,
        .optimize = optimize,
    },
});
_ = addon;

Type definitions

zig
const dts = try napi_build.generateTypeDefinition(b, .{
    .root_source_file = b.path("./src/hello.zig"),
    .output = b.path("index.d.ts"),
    .napi_module = napi,
});
b.getInstallStep().dependOn(&dts.step);

04 · Type generation

TypeScript declarations stay close to Zig exports

05 · Targets

Build surface

Targets and what they produce
TargetDetail
OpenHarmonyaarch64-linux-ohos, arm-linux-ohoseabi, x86_64-linux-ohos
Node.jshost target by default, with platform-specific .node output names
WASIwasm32-wasip1 (single-threaded) and wasm32-wasip1-threads (shared memory) builds with generated wasi/wasip1 loaders
TypeScriptindex.d.ts generation from the same addon root
Examplesbasic, init, node, allocator, memory, and benchmark fixtures

06 · Reference

API docs live on their own path

The standalone API reference covers module registration, build helpers, runtime values, binary wrappers, async descriptors, native ownership, errors, and custom TypeScript declaration overrides.

Use the API page when you need exact Zig signatures and wrapper behavior instead of the overview flow.

Open API Reference