@@ -74,20 +74,30 @@ libc stubs) — no copying files or build scripts needed.
7474
7575### 3. Build and embed in hyperlight-js
7676
77- Set ` HYPERLIGHT_CFLAGS ` before building. The hyperlight target has no libc —
78- QuickJS needs the stub headers from ` hyperlight-js-runtime/include/ ` and
79- ` -D__wasi__=1 ` to disable pthreads.
77+ The hyperlight target has no libc, so QuickJS needs stub headers from
78+ ` hyperlight-js-runtime/include/ ` and ` -D__wasi__=1 ` to disable pthreads.
79+ Set ` HYPERLIGHT_CFLAGS ` before building — the one-liner below uses
80+ ` cargo metadata ` to resolve the include path from your dependency tree:
8081
8182``` bash
83+ # Resolve CFLAGS from hyperlight-js-runtime's include/ directory
8284export HYPERLIGHT_CFLAGS=$( node -e "
8385 var m=JSON.parse(require('child_process').execSync(
8486 'cargo metadata --format-version 1 --manifest-path my-custom-runtime/Cargo.toml',
85- {encoding:'utf8',stdio:['pipe','pipe','pipe']}));
87+ {encoding:'utf8',stdio:['pipe','pipe','pipe'],maxBuffer:20*1024*1024 }));
8688 var p=m.packages.find(function(p){return p.name==='hyperlight-js-runtime'});
87- console.log('-I'+require('path').join(require('path').dirname(p.manifest_path),'include')+' -D__wasi__=1');
89+ if(p)console.log('-I'+require('path').join(
90+ require('path').dirname(p.manifest_path),'include')+' -D__wasi__=1');
8891" )
8992
90- cargo hyperlight build --manifest-path my-custom-runtime/Cargo.toml
93+ # Build the custom runtime for the hyperlight target
94+ cargo hyperlight build --manifest-path my-custom-runtime/Cargo.toml --release
95+
96+ # Tell hyperlight-js to embed the custom runtime (not the default one)
97+ export HYPERLIGHT_JS_RUNTIME_PATH=my-custom-runtime/target/x86_64-hyperlight-none/release/my-custom-runtime
98+
99+ # Rebuild hyperlight-js so the embedded runtime is updated
100+ cargo build -p hyperlight-js --release
91101```
92102
93103### 4. Use from the host
@@ -178,6 +188,93 @@ for a working example with end-to-end tests.
178188Run ` just test-native-modules ` to build the fixture for the Hyperlight
179189target and run the full integration tests.
180190
191+ ## Using js-host-api from a Downstream Node.js Project
192+
193+ If your downstream project depends on ` @hyperlight/js-host-api ` (the
194+ Node.js NAPI addon) and uses a custom runtime, you ** cannot** use a
195+ published version of the addon — the published binary has the default
196+ runtime baked in via ` include_bytes!() ` . You need to build the NAPI
197+ addon from source with your custom runtime embedded.
198+
199+ ### Why not just ` npm install ` ?
200+
201+ The ` js-host-api ` NAPI addon links against the ` hyperlight-js ` Rust crate,
202+ which embeds the runtime binary at compile time. A published npm package
203+ would contain a ` .node ` binary with the ** default** runtime — your custom
204+ native modules wouldn't be present.
205+
206+ ### The pattern: reuse Cargo's git checkout
207+
208+ Your custom runtime crate already has a Cargo dependency on
209+ ` hyperlight-js-runtime ` , which causes Cargo to clone the full
210+ ` hyperlight-js ` workspace into ` ~/.cargo/git/checkouts/ ` . The
211+ ` js-host-api ` NAPI source is included in that checkout — no separate
212+ git clone needed.
213+
214+ #### 1. Discover the checkout path
215+
216+ Use ` cargo metadata ` to find where Cargo placed the hyperlight-js
217+ workspace:
218+
219+ ``` bash
220+ HYPERLIGHT_DIR=$( node -e "
221+ var m=JSON.parse(require('child_process').execSync(
222+ 'cargo metadata --format-version 1 --manifest-path my-custom-runtime/Cargo.toml',
223+ {encoding:'utf8',stdio:['pipe','pipe','pipe'],maxBuffer:20*1024*1024}));
224+ var p=m.packages.find(function(p){return p.name==='hyperlight-js-runtime'});
225+ if(p)console.log(require('path').resolve(
226+ require('path').dirname(p.manifest_path),'..','..'));
227+ " )
228+ echo " $HYPERLIGHT_DIR "
229+ # e.g. /home/you/.cargo/git/checkouts/hyperlight-js-abc123/def456
230+ ```
231+
232+ #### 2. Build the NAPI addon with your custom runtime
233+
234+ ``` bash
235+ # Set HYPERLIGHT_CFLAGS for the guest build
236+ export HYPERLIGHT_CFLAGS=$( node -e "
237+ var m=JSON.parse(require('child_process').execSync(
238+ 'cargo metadata --format-version 1 --manifest-path my-custom-runtime/Cargo.toml',
239+ {encoding:'utf8',stdio:['pipe','pipe','pipe'],maxBuffer:20*1024*1024}));
240+ var p=m.packages.find(function(p){return p.name==='hyperlight-js-runtime'});
241+ if(p)console.log('-I'+require('path').join(
242+ require('path').dirname(p.manifest_path),'include')+' -D__wasi__=1');
243+ " )
244+
245+ # Build your custom runtime for the hyperlight target
246+ cargo hyperlight build --manifest-path my-custom-runtime/Cargo.toml --release
247+
248+ # Point hyperlight-js at your custom runtime binary
249+ export HYPERLIGHT_JS_RUNTIME_PATH=my-custom-runtime/target/x86_64-hyperlight-none/release/my-custom-runtime
250+
251+ # Clean stale builds so build.rs re-embeds the runtime
252+ cd " ${HYPERLIGHT_DIR} /src/hyperlight-js" && cargo clean -p hyperlight-js
253+
254+ # Build the NAPI addon from the Cargo checkout
255+ cd " ${HYPERLIGHT_DIR} " && just build release
256+ ```
257+
258+ #### 3. Symlink for npm dependency resolution
259+
260+ Create a symlink so npm can resolve the addon via a stable path:
261+
262+ ``` bash
263+ mkdir -p deps
264+ ln -sfn " ${HYPERLIGHT_DIR} /src/js-host-api" deps/js-host-api
265+ ```
266+
267+ In your package.json, point to js-host-api via the symlink:
268+
269+ ``` json
270+ {
271+ "dependencies" : {
272+ "@hyperlight/js-host-api" : " file:deps/js-host-api"
273+ }
274+ }
275+ ```
276+ Make sure to add ` deps ` to your ` .gitignore ` since it's a symlink to a local Cargo checkout.
277+
181278## API Reference
182279
183280### ` native_modules! `
0 commit comments