New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@crustacean/rust

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

@crustacean/rust

@crustacean/rust

latest
Source
npmnpm
Version
0.1.0
Version published
Maintainers
1
Created
Source
Crustacean

@crustacean/rust

Nx plugin for integrating Rust/Cargo into Nx workspaces.

Features

  • Inference plugin — Automatically detects Cargo.toml files and infers build, test, lint, fmt, artifacts, and prepublish targets
  • Generators — Scaffold Rust library crates, binary applications, and NAPI-RS bindings
  • Executors — Run cargo build, cargo test, cargo clippy, cargo fmt, NAPI-RS artifact collection, and prepublish
  • Nx Release — Version Rust crates via Cargo.toml (and package.json for NAPI-RS) using Nx Release

Setup

pnpm nx g @crustacean/rust:init

This initializes the workspace with:

  • Root Cargo.toml workspace (resolver 2)
  • rust-toolchain.toml (stable channel, rustfmt + clippy)
  • .rustfmt.toml with opinionated defaults
  • target/ added to .gitignore
  • Plugin registered in nx.json for automatic target inference

Generators

library

Create a Rust library crate.

pnpm nx g @crustacean/rust:library packages/my-lib
OptionTypeDefaultDescription
directorystringProject path relative to workspace root
namestringCrate name (inferred from directory)
editionstring2024Rust edition
tagsstringNx tags (comma-separated)
publishablebooleanfalseConfigure for publishing to crates.io
descriptionstringCrate description (required for publishing)
licensestringMITSPDX license identifier

application

Create a Rust binary application.

pnpm nx g @crustacean/rust:application packages/my-app
OptionTypeDefaultDescription
directorystringProject path relative to workspace root
namestringCrate name (inferred from directory)
editionstring2024Rust edition
tagsstringNx tags (comma-separated)

napi

Create a NAPI-RS library (Rust-to-Node.js binding).

pnpm nx g @crustacean/rust:napi packages/my-napi
OptionTypeDefaultDescription
directorystringProject path relative to workspace root
namestringCrate name (inferred from directory)
editionstring2024Rust edition
tagsstringNx tags (comma-separated)
publishablebooleanfalseConfigure for publishing to npm/crates.io
descriptionstringPackage description
licensestringMITSPDX license identifier
targetsstring[][x86_64-unknown-linux-gnu, ...]NAPI-RS build targets (Rust target triples)

The generator creates:

  • Cargo.toml with crate-type = ["cdylib"] and napi dependencies
  • src/lib.rs with NAPI boilerplate
  • build.rs for napi-build
  • .cargo/config.toml with linker flags for macOS
  • package.json with napi config, @napi-rs/cli devDependency, and build script
  • .npmignore excluding Rust source files

Executors

ExecutorDescription
buildBuild a Rust crate with cargo build
testRun tests with cargo test
lintLint with cargo clippy
fmtFormat with cargo fmt
artifactsCollect NAPI-RS .node binaries from CI artifacts
prepublishGenerate platform-specific npm packages for NAPI-RS

Inference Plugin

The plugin automatically detects Cargo.toml files and registers targets. Configure target names in nx.json:

{
  "plugins": [
    {
      "plugin": "@crustacean/rust/plugin",
      "options": {
        "buildTargetName": "build",
        "testTargetName": "test",
        "lintTargetName": "lint",
        "fmtTargetName": "fmt",
        "artifactsTargetName": "artifacts",
        "prepublishTargetName": "prepublish"
      }
    }
  ]
}

For NAPI-RS projects (crates with napi dependency), the plugin also infers artifacts and prepublish targets. The prepublish target automatically depends on artifacts.

Nx Release

Configure Nx Release to version Rust crates by pointing versionActions to this plugin:

{
  "release": {
    "projects": ["packages/*"],
    "version": {
      "conventionalCommits": true,
      "versionActions": "@crustacean/rust/version-actions"
    }
  }
}

The version actions handle:

  • Reading the current version from Cargo.toml
  • Updating version in Cargo.toml (preserves TOML formatting)
  • Updating version in package.json if present (NAPI-RS projects)
  • Updating dependency versions in [dependencies], [dev-dependencies], and [build-dependencies]
  • Skipping workspace = true dependencies (managed by Cargo workspace inheritance)

For mixed workspaces (Rust + JS), use release groups:

{
  "release": {
    "groups": {
      "rust": {
        "projects": ["tag:type:rust-lib"],
        "version": {
          "versionActions": "@crustacean/rust/version-actions"
        }
      },
      "js": {
        "projects": ["tag:type:js-lib"]
      }
    },
    "version": {
      "conventionalCommits": true
    }
  }
}

Publishing NAPI-RS Packages

Publishing a NAPI-RS package to npm is a multi-step process because the native .node binary must be compiled for each target platform. The final npm distribution consists of:

  • Main package (@scope/my-napi) — JS loader + type declarations
  • Platform packages (@scope/my-napi-linux-x64-gnu, @scope/my-napi-darwin-arm64, etc.) — each contains a single .node binary

The main package lists platform packages as optionalDependencies. When users install the main package, npm automatically downloads only the binary matching their OS/arch.

Overview

┌──────────────┐   ┌──────────────┐   ┌──────────────┐   ┌──────────┐   ┌─────────┐
│  CI Build    │──►│  Collect     │──►│  Prepublish  │──►│  Version │──►│ Publish │
│  Matrix      │   │  Artifacts   │   │              │   │          │   │         │
└──────────────┘   └──────────────┘   └──────────────┘   └──────────┘   └─────────┘
  napi build         napi artifacts    napi prepublish    nx release     npm publish
  (per platform)     (all .node)       (npm packages)     version        (all pkgs)

Step 1 — CI Build Matrix

Each platform is built in a separate CI job. The build executor compiles the crate with napi build --platform --release:

# .github/workflows/release.yml
strategy:
  matrix:
    include:
      - target: x86_64-unknown-linux-gnu
        os: ubuntu-latest
      - target: x86_64-unknown-linux-musl
        os: ubuntu-latest
      - target: aarch64-unknown-linux-gnu
        os: ubuntu-latest
      - target: x86_64-apple-darwin
        os: macos-13
      - target: aarch64-apple-darwin
        os: macos-14
      - target: x86_64-pc-windows-msvc
        os: windows-latest

steps:
  - uses: actions/checkout@v4
  - uses: napi-rs/setup-napi-action@v1
  - run: pnpm nx build my-napi --release --target=${{ matrix.target }}
  - uses: actions/upload-artifact@v4
    with:
      name: bindings-${{ matrix.target }}
      path: packages/my-napi/*.node

Each job produces a .node file named <binary>.<platform>.node (e.g., my_napi.linux-x64-gnu.node).

Step 2 — Collect Artifacts

After all build jobs complete, a single job downloads all artifacts and runs napi artifacts to organize them into the npm package structure:

collect:
  needs: [build]
  steps:
    - uses: actions/checkout@v4
    - uses: actions/download-artifact@v4
      with:
        path: packages/my-napi/artifacts
        merge-multiple: true
    - run: pnpm nx artifacts my-napi

The artifacts executor runs napi artifacts --output-dir ./artifacts --npm-dir ./npm which copies each .node file into the corresponding platform directory under npm/.

Executor options:

OptionTypeDefaultDescription
distPathstring./distDirectory containing built .node files
jsBindingbooleantrueGenerate JS binding files
dtsbooleantrueGenerate TypeScript declarations
argsarrayAdditional arguments passed to napi

Step 3 — Prepublish

napi prepublish generates the platform-specific npm packages. Each gets its own package.json with os and cpu fields. The main package.json is updated with optionalDependencies pointing to each platform package.

- run: pnpm nx prepublish my-napi

The prepublish executor runs napi prepublish -p npm which creates:

packages/my-napi/
├── npm/
│   ├── linux-x64-gnu/
│   │   ├── package.json    ← { "os": ["linux"], "cpu": ["x64"], ... }
│   │   └── my_napi.linux-x64-gnu.node
│   ├── darwin-arm64/
│   │   ├── package.json
│   │   └── my_napi.darwin-arm64.node
│   └── ...
├── package.json            ← updated with optionalDependencies
├── index.js                ← JS loader (auto-detects platform)
└── index.d.ts              ← TypeScript declarations

Executor options:

OptionTypeDefaultDescription
npmDirstringnpmDirectory for platform-specific packages
tagStylestringlernaGit tag style (npm or lerna)
ghReleasebooleanfalseCreate a GitHub release
ghReleaseNamestringCustom GitHub release name
ghReleaseIdstringExisting GitHub release ID
dryRunbooleanfalseDry run without file changes
argsarrayAdditional arguments passed to napi

Step 4 — Version

Use Nx Release to bump versions. The RustVersionActions automatically updates both Cargo.toml and package.json:

- run: pnpm nx release version --specifier=patch

This bumps:

  • Cargo.tomlversion = "1.0.1"
  • package.json"version": "1.0.1"

Platform-specific package versions are derived from the main package.json by napi prepublish, so they don't need separate versioning.

Step 5 — Publish

Publish all packages to npm. The main package and each platform package are published separately:

- run: |
    cd packages/my-napi
    npm publish --access public
    for dir in npm/*/; do
      cd "$dir"
      npm publish --access public
      cd ../..
    done

Alternatively, use napi prepublish with --skip-optional-publish=false (default) which handles publishing platform packages automatically when run as a prepublishOnly script.

Complete CI Workflow

name: Release

on:
  push:
    tags:
      - 'my-napi@*'

jobs:
  build:
    strategy:
      matrix:
        include:
          - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest }
          - { target: aarch64-unknown-linux-gnu, os: ubuntu-latest }
          - { target: x86_64-apple-darwin, os: macos-13 }
          - { target: aarch64-apple-darwin, os: macos-14 }
          - { target: x86_64-pc-windows-msvc, os: windows-latest }
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - uses: napi-rs/setup-napi-action@v1
      - run: pnpm nx build my-napi --release --target=${{ matrix.target }}
      - uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.target }}
          path: packages/my-napi/*.node

  publish:
    needs: [build]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: pnpm
          registry-url: https://registry.npmjs.org
      - run: pnpm install --frozen-lockfile
      - uses: actions/download-artifact@v4
        with:
          path: packages/my-napi/artifacts
          merge-multiple: true
      - run: pnpm nx artifacts my-napi
      - run: pnpm nx prepublish my-napi --no-gh-release
      - run: |
          cd packages/my-napi
          npm publish --access public
          for dir in npm/*/; do
            (cd "$dir" && npm publish --access public)
          done
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

FAQ

Are platform-specific packages Nx projects?

No. They are generated artifacts created by napi prepublish under the npm/ directory. They don't have Cargo.toml and are not registered in the Nx workspace. Their version is derived from the main package.json — no separate versioning needed.

Does VersionActions bump platform package versions?

No, and it doesn't need to. Platform packages are regenerated by napi prepublish each time, inheriting the version from the main package.json. The VersionActions bumps Cargo.toml + main package.json, which is sufficient.

Can I use nx release publish for NAPI-RS packages?

nx release publish works for the main package but won't automatically publish platform packages (since they aren't Nx projects). Use the shell loop shown above, or configure prepublishOnly in package.json to handle it via npm lifecycle scripts.

What about napi prepublish --gh-release?

If you use GitHub Releases to distribute binaries (alternative to npm), pass --ghRelease to the prepublish executor. This uploads .node files as GitHub Release assets. Users then download the binary directly instead of via npm optionalDependencies.

FAQs

Package last updated on 08 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts