1- The ` node-api ` Zig package provides [ Node-API] ( https://nodejs.org/api/n-api.html ) bindings for writing idiomatic Zig addons for V8-based runtimes like Node.JS or Bun.
2- Thanks to its conventions-based approach it bridges the gap seamlessly, with almost no Node-API specific code!
1+ The ` node-api ` module provides [ Node-API] ( https://nodejs.org/api/n-api.html ) bindings for writing idiomatic Zig addons
2+ for V8-based runtimes like Node.JS or Bun. Thanks to its conventions-based approach it bridges the gap seamlessly,
3+ with almost no Node-API specific code!
34
45![ build-badge] ( https://img.shields.io/github/actions/workflow/status/typesafe/node-api-zig/ci.yml )
56![ test-badge] ( https://img.shields.io/endpoint?url=https%3A%2F%2Fgist.githubusercontent.com%2Ftypesafe%2F26882516c7ac38bf94a81784f966bd86%2Fraw%2Fnode-api-zig-test-badge.json )
67
7- ## Features
8+ ## Key Features
89
910- ** function mapping** , including async support (auto-conversion to Promises)
10- - ** class mapping** , incl. support for fields, instance (async) methods, satic (async) methods.
11- - ** auto- wrapping** of native objects instances, similar to defining classes but for instances created in native Zig code
11+ - ** class mapping** , incl. support for fields, instance (async) methods and satic (async) methods.
12+ - ** wrapping/unwrapping ** of native objects instances
1213- ** memory management** with convention-based ` init ` , ` deinit ` support & ` allocator ` injection
13- - ` errorunion ` support
14- - mapping JS values
15- - by value: through (de)serialization or various types
16- - by reference
14+ - ** error handling ** with ` errorunion ` support
15+ - Convention-base ** type conversion **
16+ - ** by value** : through (de)serialization or various types with automatic memory management
17+ - ** by reference** :
1718 - Zig-managed values: through pointers to (wrapped) native Zig values
1819 - JS-managed values: through wrappers types (` NodeValue ` et.al.) for read/write
19- - typesafe callbacks: ` NodeFunction(fn (u32, u32) !u32) `
20-
21- ## Example
22-
23- ``` zig
24- const node_api = @import("node-api");
25- const Options = @import("Options");
26-
27- comptime {
28- // or node_api.init(fn (node) NodeValue) for runtime values
29- node_api.@"export"(encrypt);
30- }
31-
32- fn encrypt(value: []const u8, options: Options, allocator: std.mem.Allocator) ![]const u8 {
33- const res = allocator.alloc(u8, 123);
34- errdefer allocator.free(res);
35-
36- // ...
37-
38- return res; // freed by node-api
39- }
40-
41- ```
42-
43- ``` TypeScript
44- import { createRequire } from " module" ;
45- const require = createRequire (import .meta .url );
46-
47- const encrypt = require (" zig-module.node" );
48-
49- // call zig function
50- const m = encrypt (" secret" , { salt: " ..." });
51-
52- ```
53-
54- TODO:
55-
56- - [ ] auto-register class for members of type ` type ` .
57- - [ ] Make ` NodeFunction ` thread safe by convention when it is used in an async function/method.
58- - [ ] Add ` NodeObject ` for "by reference" access to JS objects from Zig
59- - [ ] Add ` NodeArray ` for "by reference" access to JS objects from Zig
60- - [ ] Add support for externals
61- - [ ] ` External `
62- - [ ] ` ExternalBuffer `
63- - [ ] ` ExternalArrayBuffer `
64- - [ ] Use ` Result(T, E) ` as alternative to ` errorunion ` s for improved error messages.
20+ - ** type-safe callbacks** : ` NodeFunction(fn (u32, u32) !u32) `
6521
66- # Getting started
22+ ## Getting started
6723
6824Install the ` node_api ` (note the underscore) dependency
6925
7026``` sh
71- > zig fetch --save https://github.com/typesafe/node-api-zig/archive/refs/tags/v0.0.3 -beta.tar.gz
27+ > zig fetch --save https://github.com/typesafe/node-api-zig/archive/refs/tags/v0.0.4 -beta.tar.gz
7228```
7329
74- Add the ` node-api ` (note the hyphen) module to your library.
30+ Add the ` node-api ` module to your library:
7531
7632``` zig
7733const std = @import("std");
@@ -90,9 +46,9 @@ pub fn build(b: *std.Build) void {
9046 mod.addImport("node-api", node_api.module("node-api"));
9147
9248 const lib = b.addLibrary(.{
93- // needed on Linux
49+ // if Linux
9450 .use_llvm = true,
95- .name = "my-native-node-library ",
51+ .name = "my-native-node-module ",
9652 .root_module = mod,
9753 });
9854
@@ -103,21 +59,53 @@ pub fn build(b: *std.Build) void {
10359Initialize your Node-API extension:
10460
10561``` zig
106- const std = @import("std");
107- const node = @import("node-api");
62+ const node_api = @import("node-api");
10863
10964comptime {
110- node.@"export"(.{
111- // functions, types (for classes), values
112- });
65+ // export encrypt function (or types, or values or pointers)
66+ node_api.@"export"(.{
67+ .encrypt = encrypt,
68+ // ...
69+ });
70+ }
71+
72+ fn encrypt(
73+ // serialized from JS string, borrowed memory
74+ value: []const u8,
75+ // serialized from JS object by value (use *Options for wrapped native instances)
76+ options: Options,
77+ // "injected" by convention, any memory allocated with it is freed after returning to JS
78+ allocator: std.mem.Allocator,
79+ ) ![]const u8 {
80+ const res = allocator.alloc(u8, 123);
81+
82+ // ...
83+
84+ return res; // freed by node-api
11385}
11486```
11587
116- # Features
88+ Use your library as node module:
89+
90+ ``` TypeScript
91+ import { createRequire } from " module" ;
92+ const require = createRequire (import .meta .url );
11793
118- ## Initialize Module
94+ const { encrypt } = require (" my-native-node-module.node" );
95+
96+ const m = encrypt (" secret" , { salt: " ..." });
97+
98+ ```
99+
100+ ## Features
101+
102+ ### Module Initialization
103+
104+ There are 2 options to initialize a module:
105+
106+ - ` node_api.@"export" ` : conveniant for exporting comptime values, which is very likely
107+ - ` node_api.init(fn (node: NodeContext) !NodeValue) ` : for exporting runtime values
119108
120- Call the ` node_api.register ` method at compile time:
121109
122110``` Zig
123111comptime {
@@ -129,10 +117,11 @@ fn init(node: node_api.NodeContext) !?node_api.NodeValue {
129117}
130118```
131119
132- ``` TypeScript
133- // `fromZig` = return value of `init` above.
134- import fromZig from (zig -module .node );
135- ```
120+ ### NodeContext
121+
122+ The ` node_api.init ` initialization function as well as any
123+
124+
136125
137126## Type Conversions
138127
0 commit comments