Skip to content
Merged
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
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Test fixtures and snapshots:
## CLI Usage

```bash
# Run a task defined in vite.config.json
# Run a task defined in vite-task.json
vite run <task> # run task in current package
vite run <package>#<task> # run task in specific package
vite run <task> -r # run task in all packages (recursive)
Expand Down Expand Up @@ -67,7 +67,7 @@ vite lint [args...] # run oxlint

## Task Configuration

Tasks are defined in `vite.config.json`:
Tasks are defined in `vite-task.json`:

```json
{
Expand All @@ -83,7 +83,7 @@ Tasks are defined in `vite.config.json`:

## Task Dependencies

1. **Explicit**: Defined via `dependsOn` in `vite.config.json` (skip with `--ignore-depends-on`)
1. **Explicit**: Defined via `dependsOn` in `vite-task.json` (skip with `--ignore-depends-on`)
2. **Topological**: Based on package.json dependencies
- With `-r/--recursive`: runs task across all packages in dependency order
- With `-t/--transitive`: runs task in current package and its dependencies
Expand Down Expand Up @@ -116,4 +116,4 @@ These patterns are enforced by `.clippy.toml`:
## Quick Reference

- **Task Format**: `package#task` (e.g., `app#build`, `@test/utils#lint`)
- **Config File**: `vite.config.json` in each package
- **Config File**: `vite-task.json` in each package
6 changes: 6 additions & 0 deletions crates/vite_path/src/absolute/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ impl Debug for AbsolutePath {
}
}

impl Display for AbsolutePath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.0.display(), f)
}
}

impl Serialize for AbsolutePath {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"cacheScripts": true,
"tasks": {
"no-cache-task": {
"command": "print-file test.txt",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,16 @@ steps = [
name = "pass-through env added"
steps = [
"vite run test # cache miss",
"json-edit vite.config.json \"_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']\" # add pass-through env",
"json-edit vite-task.json \"_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']\" # add pass-through env",
"vite run test # cache miss: pass-through env added",
]

[[e2e]]
name = "pass-through env removed"
steps = [
"json-edit vite.config.json \"_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']\" # setup",
"json-edit vite-task.json \"_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']\" # setup",
"vite run test # cache miss",
"json-edit vite.config.json \"delete _.tasks.test.passThroughEnvs\" # remove pass-through env",
"json-edit vite-task.json \"delete _.tasks.test.passThroughEnvs\" # remove pass-through env",
"vite run test # cache miss: pass-through env removed",
]

Expand All @@ -44,7 +44,7 @@ steps = [
"vite run test # cache miss",
"mkdir -p subfolder",
"cp test.txt subfolder/test.txt",
"json-edit vite.config.json \"_.tasks.test.cwd = 'subfolder'\" # change cwd",
"json-edit vite-task.json \"_.tasks.test.cwd = 'subfolder'\" # change cwd",
"vite run test # cache miss: cwd changed",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Task Details:

> cp test.txt subfolder/test.txt

> json-edit vite.config.json "_.tasks.test.cwd = 'subfolder'" # change cwd
> json-edit vite-task.json "_.tasks.test.cwd = 'subfolder'" # change cwd

> vite run test # cache miss: cwd changed
~/subfolder$ print-file test.txt ✗ cache miss: working directory changed, executing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Task Details:
→ Cache miss: no previous cache entry found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

> json-edit vite.config.json "_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']" # add pass-through env
> json-edit vite-task.json "_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']" # add pass-through env

> vite run test # cache miss: pass-through env added
$ print-file test.txt ✗ cache miss: pass-through env config changed, executing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ assertion_line: 203
expression: e2e_outputs
input_file: crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-reasons
---
> json-edit vite.config.json "_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']" # setup
> json-edit vite-task.json "_.tasks.test.passThroughEnvs = ['MY_PASSTHROUGH']" # setup

> vite run test # cache miss
$ print-file test.txt
Expand All @@ -24,7 +24,7 @@ Task Details:
→ Cache miss: no previous cache entry found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

> json-edit vite.config.json "delete _.tasks.test.passThroughEnvs" # remove pass-through env
> json-edit vite-task.json "delete _.tasks.test.passThroughEnvs" # remove pass-through env

> vite run test # cache miss: pass-through env removed
$ print-file test.txt ✗ cache miss: pass-through env config changed, executing
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"cacheScripts": true,
"tasks": {
"test": {
"command": "print-file test.txt",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"cacheScripts": true,
"tasks": {
"task-a": {
"command": "echo a",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"cacheScripts": true,
"tasks": {
"hello": {
"command": "print-env FOO",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"cacheScripts": true,
"tasks": {
"abort": {
"command": "node -e \"process.kill(process.pid, 6)\""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cacheScripts": true
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,16 @@ export type Task = {
}
);

export type Tasks = { [key in string]?: Task };
export type RunConfig = {
/**
* Enable cache for all scripts from package.json.
*
* This option can only be set in the workspace root's config file.
* Setting it in a package's config will result in an error.
*/
cacheScripts?: boolean;
/**
* Task definitions
*/
tasks?: { [key in string]?: Task };
};
20 changes: 17 additions & 3 deletions crates/vite_task_graph/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{collections::HashSet, sync::Arc};

use monostate::MustBe;
use serde::Serialize;
pub use user::{UserCacheConfig, UserConfigFile, UserTaskConfig};
pub use user::{EnabledCacheConfig, UserCacheConfig, UserRunConfig, UserTaskConfig};
use vite_path::AbsolutePath;
use vite_str::Str;

Expand Down Expand Up @@ -91,14 +91,28 @@ pub enum ResolveTaskConfigError {
}

impl ResolvedTaskConfig {
/// Resolve from package.json script only
/// Resolve from package.json script only (no vite-task.json config for this task)
///
/// The `cache_scripts` parameter determines whether caching is enabled for the script.
/// When `true`, caching is enabled with default settings.
/// When `false`, caching is disabled.
pub fn resolve_package_json_script(
package_dir: &Arc<AbsolutePath>,
package_json_script: &str,
cache_scripts: bool,
) -> Self {
let cache_config = if cache_scripts {
UserCacheConfig::Enabled {
cache: None,
enabled_cache_config: EnabledCacheConfig { envs: None, pass_through_envs: None },
}
} else {
UserCacheConfig::Disabled { cache: MustBe!(false) }
};
let options = UserTaskOptions { cache_config, ..Default::default() };
Self {
command: package_json_script.into(),
resolved_options: ResolvedTaskOptions::resolve(UserTaskOptions::default(), package_dir),
resolved_options: ResolvedTaskOptions::resolve(options, package_dir),
}
}

Expand Down
38 changes: 20 additions & 18 deletions crates/vite_task_graph/src/config/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,24 @@ pub struct UserTaskConfig {
pub options: UserTaskOptions,
}

/// User configuration file structure for `vite.config.*`
#[derive(Debug, Deserialize)]
pub struct UserConfigFile {
pub tasks: UserConfigTasks,
}

/// Type of the `tasks` field in `vite.config.*`
/// User configuration structure for `run` field in `vite.config.*`
#[derive(Debug, Default, Deserialize)]
#[cfg_attr(test, derive(TS))]
#[serde(transparent)]
#[cfg_attr(test, ts(rename = "Tasks"))]
pub struct UserConfigTasks(pub HashMap<Str, UserTaskConfig>);
#[cfg_attr(test, derive(TS), ts(optional_fields, rename = "RunConfig"))]
#[serde(rename_all = "camelCase")]
pub struct UserRunConfig {
/// Enable cache for all scripts from package.json.
///
/// This option can only be set in the workspace root's config file.
/// Setting it in a package's config will result in an error.
pub cache_scripts: Option<bool>,

/// Task definitions
pub tasks: Option<HashMap<Str, UserTaskConfig>>,
}

impl UserConfigTasks {
/// TypeScript type definitions for user task configuration.
pub const TS_TYPE: &str = include_str!("../../task-config.ts");
impl UserRunConfig {
/// TypeScript type definitions for user run configuration.
pub const TS_TYPE: &str = include_str!("../../run-config.ts");

/// Generates TypeScript type definitions for user task configuration.
#[cfg(test)]
Expand Down Expand Up @@ -155,7 +157,7 @@ impl UserConfigTasks {
.expect("oxfmt not found in packages/tools");

let mut child = Command::new(oxfmt_path)
.arg("--stdin-filepath=task-config.ts")
.arg("--stdin-filepath=run-config.ts")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
Expand All @@ -179,13 +181,13 @@ impl UserConfigTasks {
mod ts_tests {
use std::{env, path::PathBuf};

use super::UserConfigTasks;
use super::UserRunConfig;

#[test]
fn typescript_generation() {
let file_path =
PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("task-config.ts");
let ts = UserConfigTasks::generate_ts_definition().replace("\r", "");
PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("run-config.ts");
let ts = UserRunConfig::generate_ts_definition().replace("\r", "");

if env::var("VT_UPDATE_TS_TYPES").unwrap_or_default() == "1" {
std::fs::write(&file_path, ts).unwrap();
Expand Down
Loading