Skip to content

Commit c44d7c3

Browse files
wan9chiclaude
andcommitted
fix(napi): keep vite_task_client_napi type-defs out of consumer bindings
This crate is embedded as a cdylib artifact dependency of `vite_task`. napi-derive's `type-def` feature is force-enabled by feature unification with consumers that need it, so it would otherwise write this crate's `#[napi]` items (RunnerClient/load) into the consumer's shared NAPI_TYPE_DEF_TMP_FOLDER, which @napi-rs/cli sweeps into the consumer's generated binding as dead exports (the symbols live in the separately-loaded addon, not the consumer's .node). build.rs redirects this crate's type-def emission to an isolated sink and prunes any stale entry a pre-redirect build left in the consumer's (reused) folder. The public JS surface is the hand-written @voidzero-dev/vite-task-client package, so these generated defs are never needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 6e634c6 commit c44d7c3

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
1+
#![expect(
2+
clippy::disallowed_types,
3+
reason = "build.rs interfaces with std::path and cargo's env-var API"
4+
)]
5+
16
extern crate napi_build;
27

8+
use std::{env, fs, path::PathBuf};
9+
310
fn main() {
411
napi_build::setup();
12+
13+
// Keep this crate's napi-derive type-defs out of any consumer's generated
14+
// binding.
15+
//
16+
// `vite_task_client_napi` is embedded as a cdylib *artifact* dependency of
17+
// `vite_task`. napi-derive's `type-def` feature is force-enabled by feature
18+
// unification with consumers that need it (e.g. vite-plus's CLI binding), so
19+
// disabling the feature here has no effect. By default napi-derive then
20+
// writes this crate's `#[napi]` items (`RunnerClient`/`load`) into the
21+
// consumer's shared `NAPI_TYPE_DEF_TMP_FOLDER`, which `@napi-rs/cli` sweeps
22+
// into the consumer's `index.cjs`/`index.d.cts` as dead exports (the symbols
23+
// live in the separately-loaded addon, not the consumer's `.node`). The
24+
// public JS surface is the hand-written `@voidzero-dev/vite-task-client`
25+
// package, so these generated defs are never needed.
26+
//
27+
// `@napi-rs/cli` reuses that folder across builds without pruning it, so
28+
// first remove any entry a pre-redirect build left there, then redirect this
29+
// crate's emission to an isolated, clearly-named sink. The override applies
30+
// only to this crate's rustc invocation, where the napi-derive proc-macro
31+
// reads the env at expansion time, so consumers' own type-defs are
32+
// unaffected.
33+
println!("cargo::rerun-if-env-changed=NAPI_TYPE_DEF_TMP_FOLDER");
34+
let pkg = env::var("CARGO_PKG_NAME").expect("CARGO_PKG_NAME not set");
35+
if let Ok(consumer_folder) = env::var("NAPI_TYPE_DEF_TMP_FOLDER") {
36+
let _ = fs::remove_file(PathBuf::from(consumer_folder).join(&pkg));
37+
}
38+
let sink = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set"))
39+
.join("discarded-napi-type-defs");
40+
fs::create_dir_all(&sink).expect("failed to create napi type-def sink dir");
41+
println!("cargo::rustc-env=NAPI_TYPE_DEF_TMP_FOLDER={}", sink.display());
542
}

0 commit comments

Comments
 (0)