Skip to content

Commit ec0f1e7

Browse files
committed
update readme
1 parent 6cb4117 commit ec0f1e7

File tree

1 file changed

+61
-72
lines changed

1 file changed

+61
-72
lines changed

README.md

Lines changed: 61 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,33 @@
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

6824
Install 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
7733
const 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 {
10359
Initialize 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
10964
comptime {
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
123111
comptime {
@@ -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

Comments
 (0)