Socket
Book a DemoInstallSign in
Socket

vite-plus

Package Overview
Dependencies
Maintainers
6
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vite-plus

This package provides the JavaScript-to-Rust bridge that enables vite-plus to execute JavaScript tooling (like Vite, Vitest, and oxlint) from the Rust core. It uses NAPI-RS to create native Node.js bindings.

latest
npmnpm
Version
0.0.0-ab0b0858cb619f270f5e0a698fea3d6f5622a761
Version published
Maintainers
6
Created
Source

Vite+ Local CLI Package

Overview

This package provides the JavaScript-to-Rust bridge that enables vite-plus to execute JavaScript tooling (like Vite, Vitest, and oxlint) from the Rust core. It uses NAPI-RS to create native Node.js bindings.

Usage

Install

Add to your project's devDependencies:

pnpm add -D @voidzero-dev/vite-plus
# or
npm install -D @voidzero-dev/vite-plus
# or
yarn add -D @voidzero-dev/vite-plus

Built-in Commands

Build

build command will use rolldown-vite to build your project.

npx vite build

Test

test command will use vitest to test your project.

npx vite test

Lint

lint command will use oxlint to lint your project.

npx vite lint

Task runner

You can use vite run to run any task that you want.

Run a task on the current project.

npx vite run <task-name>

Run all task with the same name in monorepo.

npx vite run -r <task-name>

Architecture

How It Works

The architecture follows a callback-based pattern where JavaScript functions resolve tool paths and pass them to Rust for execution:

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐
│   JavaScript    │────▶│   NAPI Bridge    │────▶│    Rust Core    │
│   (bin.ts)      │     │   (binding/)     │     │  (vite_task)    │
└─────────────────┘     └──────────────────┘     └─────────────────┘
        │                        │                         │
        ▼                        ▼                         ▼
   Resolves tool            Converts JS              Executes tools
   binary paths           callbacks to Rust         with resolved paths

Key Components

1. JavaScript Layer (src/)

The JavaScript layer is responsible for resolving tool binary paths:

  • bin.ts: Entry point that initializes the CLI with tool resolvers
  • vite.ts: Resolves the Vite binary path for build commands
  • test.ts: Resolves the Vitest binary path for test commands
  • lint.ts: Resolves the oxlint binary path for linting
  • index.ts: Exports the defineConfig helper for Vite configuration

Each resolver function returns:

{
  binPath: string,    // Absolute path to the tool's binary
  envs: Record<string, string>  // Environment variables to set
}

2. NAPI Binding Layer (binding/)

The binding layer provides the JavaScript-to-Rust bridge using NAPI-RS:

  • src/lib.rs: Defines the NAPI bindings and type conversions
  • index.d.ts: TypeScript type definitions (auto-generated)
  • index.js: Native module loader (auto-generated)

The binding converts JavaScript callbacks into Rust futures using ThreadsafeFunction.

3. Rust Core Integration

The Rust core (crates/vite_task) receives the tool resolvers through CliOptions:

pub struct CliOptions {
    pub lint: LintFn,  // Callback to resolve lint tool
    pub vite: ViteFn,  // Callback to resolve vite tool
    pub test: TestFn,  // Callback to resolve test tool
}

Execution Flow

  • Initialization: bin.ts calls run() with tool resolver functions
  • Command Parsing: Rust parses CLI arguments to determine which command to run
  • Tool Resolution: When a command needs a tool (e.g., vite build):
    • Rust calls back to JavaScript through NAPI
    • JavaScript resolver finds the tool's binary path
    • Path is returned to Rust
  • Execution: Rust executes the tool binary with appropriate arguments

Example: Vite Build Command

When a user runs vite-plus build:

  • Rust identifies this as a Build command
  • Calls the vite callback function
  • JavaScript vite.ts resolves vite/bin/vite.js path
  • Returns path to Rust
  • Rust executes: node /path/to/vite.js build [args]

Development

Building

# Build the native binding
pnpm build

# Or watch for changes
pnpm build:debug

Adding a New Tool

  • Create a resolver in src/:
// src/mytool.ts
export async function mytool() {
  const binPath = require.resolve('mytool/bin/cli.js');
  return { binPath, envs: {} };
}
  • Add to CliOptions in binding/src/lib.rs:
pub struct CliOptions {
    // ... existing fields
    pub mytool: Arc<ThreadsafeFunction<(), Promise<JsCommandResolvedResult>>>,
}
  • Wire it up in bin.ts:
import { mytool } from './mytool.js';
run({ lint, vite, test, mytool });

Benefits of This Architecture

  • Tool Resolution in JavaScript: Leverages Node.js module resolution to find tools
  • Execution in Rust: Benefits from Rust's performance and concurrency
  • Type Safety: Full type safety across the JS-Rust boundary
  • Flexibility: Easy to add new tools without changing core logic
  • Environment Handling: Can pass environment variables per tool

Dependencies

  • napi: Node-API bindings for Rust
  • napi-derive: Procedural macros for NAPI
  • vite, vitest, oxlint: The actual tools being wrapped

FAQs

Package last updated on 15 Jan 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