A monorepo task runner (like nx/turbo) with intelligent caching and dependency resolution.
Task Execution: Run tasks across monorepo packages with automatic dependency ordering.
# Built-in commands
vp build # Run Vite build (dedicated command)
vp test # Run Vitest (dedicated command)
vp lint # Run oxlint (dedicated command)
# Run tasks across packages (explicit mode)
vp run build -r # recursive with topological ordering
vp run app#build web#build # specific packages
vp run build -r --no-topological # recursive without implicit deps
# Run task in current package (implicit mode - for non-built-in tasks)
vp run dev # runs dev script from package.json- Entry:
crates/vite_task/src/lib.rs- CLI parsing and main logic - Workspace:
crates/vite_task/src/config/workspace.rs- Loads packages, creates task graph - Task Graph:
crates/vite_task/src/config/task_graph_builder.rs- Builds dependency graph - Execution:
crates/vite_task/src/schedule.rs- Executes tasks in dependency order
-
Explicit (always applied): Defined in
vite-task.json{ "tasks": { "test": { "command": "jest", "dependsOn": ["build", "lint"] } } } -
Implicit (when
--topological): Based on package.json dependencies- If A depends on B, then A#build depends on B#build automatically
-
Topological Flag: Controls implicit dependencies from package relationships
- Default: ON for
--recursive, OFF otherwise - Toggle with
--no-topologicalto disable
- Default: ON for
-
Boolean Flags: All support
--no-*pattern for explicit disable- Example:
--recursivevs--no-recursive - Conflicts handled by clap
- If you want to add a new boolean flag, follow this pattern
- Example:
-
Type Safety: All paths use typed
vite_pathinstead ofstd::pathfor better safety- Absolute Paths:
vite_path::AbsolutePath/AbsolutePathBuf - Relative Paths:
vite_path::RelativePath/RelativePathBuf
- Absolute Paths:
-
Usage Guidelines:
- Use methods such as
strip_prefix/joinprovided invite_pathfor path operations instead of converting to std paths - Only convert to std paths when interfacing with std library functions, and this should be implicit in most cases thanks to
AsRef<Path>implementations - Add necessary methods in
vite_pathinstead of falling back to std path types
- Use methods such as
-
Converting from std paths (e.g.,
TempDir::path()):let temp_path = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap();
-
Function signatures: Prefer
&AbsolutePathover&std::path::Path -
Passing to std functions:
AbsolutePathimplementsAsRef<Path>, use.as_path()when explicit&Pathis required
All new Rust code must follow the custom clippy rules defined in .clippy.toml (disallowed types, macros, and methods). Existing code may not fully comply due to historical reasons.
All user-facing output must go through shared output modules instead of raw print calls.
- Rust: Use
vite_shared::outputfunctions (info,warn,error,note,success) — never rawprintln!/eprintln!(enforced by clippydisallowed-macros) - TypeScript: Use
packages/cli/src/utils/terminal.tsfunctions (infoMsg,warnMsg,errorMsg,noteMsg,log) — never rawconsole.log/console.error
- Run
vp check --fixbefore committing to format and lint code
- Compound Commands:
"build": "tsc && rollup"splits into subtasks - Task Format:
package#task(e.g.,app#build) - Path Types: Use
vite_pathtypes instead ofstd::pathtypes for type safety - Tests: Run
cargo test -p vite_taskto verify changes - Debug: Use
--debugto see cache operations
- Run
cargo testto execute all tests - You never need to run
pnpm installin the test fixtures dir, vite-plus should able to load and parse the workspace withoutpnpm install.
- Run
pnpm bootstrap-clifrom the project root to build all packages and install the global CLI- This builds all
@voidzero-dev/*andvite-pluspackages - Compiles the Rust NAPI bindings and the
vpRust binary - Installs the CLI globally to
~/.vite-plus/
- This builds all
Snap tests are located in packages/cli/snap-tests/ (local CLI) and packages/cli/snap-tests-global/ (global CLI). Each test case is a directory containing:
package.json- Package configuration for the teststeps.json- Commands to run and environment variablessrc/- Source files for the testsnap.txt- Expected output (generated/updated by running the test)
# Run all snap tests (local + global)
pnpm -F vite-plus snap-test
# Run only local CLI snap tests
pnpm -F vite-plus snap-test-local
pnpm -F vite-plus snap-test-local <name-filter>
# Run only global CLI snap tests
pnpm -F vite-plus snap-test-global
pnpm -F vite-plus snap-test-global <name-filter>The snap test will automatically generate/update the snap.txt file with the command outputs. It exits with zero status even if there are output differences; you need to manually check the diffs(git diff) to verify correctness.