我如何将我的 Rust Bun 版本管理器 (bum) CLI 发布到 NPM 包

发布: (2025年12月7日 GMT+8 12:49)
3 min read
原文: Dev.to

Source: Dev.to

背景

我构建了一个名为 bum 的 CLI——一个用 Rust 编写的快速 Bun 版本管理器。它在本地运行得很好,但我希望任何人都能运行:

npx @owenizedd/bum use 1.3.3

而无需安装 Rust 或编译任何东西。事实证明这完全可行!我从 lekoarts.de 的一篇关于使用 napi‑rs 在 npm 上发布 Rust CLI 的文章中学到了这点。

设置

napi-rs 添加到你的 Rust 项目

# Cargo.toml
[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
napi = "2.16"
napi-derive = "2.16"

[build-dependencies]
napi-build = "2.1"

napi 函数包装你的 CLI

// src/lib.rs
use napi_derive::napi;

#[napi]
pub fn run(args: Vec) -> napi::Result {
    let rt = tokio::runtime::Runtime::new()
        .map_err(|e| napi::Error::from_reason(format!("Failed to create runtime: {}", e)))?;

    // Your CLI logic here
    rt.block_on(async {
        // run_commands(args).await
    });

    Ok(())
}

创建一个简单的 bin.js

#!/usr/bin/env node

const { run } = require("./index");
const args = process.argv.slice(2);

try {
  run(args);
} catch (e) {
  console.error(e);
  process.exit(1);
}

配置 package.json

{
  "name": "@owenizedd/bum",
  "bin": "bin.js",
  "napi": {
    "name": "bum",
    "triples": {
      "defaults": true,
      "additional": [
        "aarch64-apple-darwin",
        "x86_64-apple-darwin",
        "x86_64-unknown-linux-musl",
        "aarch64-unknown-linux-gnu"
      ]
    }
  }
}

OpenSSL 跨编译噩梦

reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
zip = { version = "1.1", default-features = false, features = ["deflate"] }

每个平台(例如 darwin-arm64linux-x64-gnu)都会作为单独的 npm 包发布。最初我们忘记更新它们的 package.json 版本,导致 npm 找不到这些包。

解决方案:在 CI 中同步平台包版本

- name: Sync platform package versions
  run: |
    VERSION=$(node -p "require('./package.json').version")
    for dir in npm/*/; do
      node -e "
        const fs = require('fs');
        const pkg = JSON.parse(fs.readFileSync('$dir/package.json'));
        pkg.version = '$VERSION';
        fs.writeFileSync('$dir/package.json', JSON.stringify(pkg, null, 2));
      "
    done

打包陷阱

我们最初尝试使用 bun build bin.ts 编译 TypeScript。Bun 将 require('./index') 内联,并用哈希硬编码了 .node 文件名,导致代码损坏:

// Broken bundling result
nativeBinding = require("./bum.darwin-arm64-7xvffnqw.node");

正确(可工作)的导入应该是:

// Correct import
nativeBinding = require("./bum.darwin-arm64.node");

解决方案:bin.js 使用普通的 JavaScript,避免打包。

结果

现在任何人都可以运行:

npx @owenizedd/bum use 1.3.3

它在 macOS、Linux 和 Windows 上都能工作(其他平台仍在测试中)。

参考资料

Back to Blog

相关文章

阅读更多 »

内核 Rust 实验的结束

抱歉,我无法访问外部链接。请提供您希望翻译的具体摘录或摘要文本,我将为您翻译成简体中文。