Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,28 @@ extern crate napi_build;

fn main() {
napi_build::setup();

// Expose the npm package version (from package.json) so the client can report
// it in its user agent. The Cargo package version is kept at 0.0.0 by napi, so
// CARGO_PKG_VERSION is not usable here. The release artifacts are built via
// `yarn build` from a checkout whose package.json holds the release version,
// so reading it here picks up the real version regardless of the build env.
// Falls back to CARGO_PKG_VERSION if package.json can't be read.
let version = std::fs::read_to_string("package.json")
.ok()
.and_then(|pkg| {
pkg.lines().find_map(|line| {
line.trim()
.strip_prefix("\"version\":")
.map(|rest| {
rest.trim()
.trim_matches(|c| c == ',' || c == '"' || c == ' ')
.to_string()
})
})
})
.unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string());
Comment on lines +12 to +25

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fragile JSON parsing could break on valid formatting variations.

The manual line-by-line string matching requires "version": with no space before the colon. This will fail on valid JSON formatted as "version" : "1.4.0" or if formatting tools reflow the file. When parsing fails, the fallback to CARGO_PKG_VERSION (0.0.0) defeats the purpose of this PR.

🔧 Proposed fix using serde_json for robust parsing

Add serde_json to [build-dependencies] in Cargo.toml:

[build-dependencies]
napi-build = "..."
serde_json = "1.0"

Then replace the manual parsing with:

-    let version = std::fs::read_to_string("package.json")
-        .ok()
-        .and_then(|pkg| {
-            pkg.lines().find_map(|line| {
-                line.trim()
-                    .strip_prefix("\"version\":")
-                    .map(|rest| {
-                        rest.trim()
-                            .trim_matches(|c| c == ',' || c == '"' || c == ' ')
-                            .to_string()
-                    })
-            })
-        })
-        .unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string());
+    let version = std::fs::read_to_string("package.json")
+        .ok()
+        .and_then(|pkg| {
+            serde_json::from_str::<serde_json::Value>(&pkg)
+                .ok()?
+                .get("version")?
+                .as_str()
+                .map(|s| s.to_string())
+        })
+        .unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string());

This handles all valid JSON formats and is more maintainable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.rs` around lines 12 - 25, The current manual line-based parsing in
build.rs that computes the local variable version is brittle; instead add
serde_json = "1.0" to [build-dependencies] in Cargo.toml and replace the manual
read/line/strip_prefix logic with a robust JSON parse using serde_json::from_str
to extract the "version" field (falling back to
env!("CARGO_PKG_VERSION").to_string() if parsing or key extraction fails).
Locate the code that defines version in build.rs (and the use of
env!("CARGO_PKG_VERSION")) and update it to read package.json, parse it with
serde_json::Value (or a small struct with a version field), and use that value
as the version.


println!("cargo:rustc-env=NPM_PKG_VERSION={version}");
println!("cargo:rerun-if-changed=package.json");
}
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ impl HypersyncClient {
/// Create a new client with given config
#[napi(constructor)]
pub fn new(cfg: ClientConfig) -> napi::Result<HypersyncClient> {
Self::new_with_agent(cfg, format!("hscn/{}", env!("CARGO_PKG_VERSION")))
// NPM_PKG_VERSION is the package.json version, injected by build.rs.
// (CARGO_PKG_VERSION is 0.0.0 because napi keeps the Cargo version static.)
Self::new_with_agent(cfg, format!("hscn/{}", env!("NPM_PKG_VERSION")))
}

/// Create a new client with custom user agent
Expand Down