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
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"no-cache-task": {
"command": "print-file test.txt",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"test": {
"command": "print-file test.txt",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"cached-task": {
"command": "print-file test.txt",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"task-a": {
"command": "echo a",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"hello": {
"command": "print-env FOO",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"abort": {
"command": "node -e \"process.kill(process.pid, 6)\""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"read-stdin": {
"command": "read-stdin",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"check-tty": {
"command": "check-tty",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cacheScripts": true,
"cache": true,
"tasks": {
"check-tty": {
"command": "check-tty",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"cacheScripts": true
"cache": true
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
// Smoke test: enables caching for all package.json scripts.
"cacheScripts": true
"cache": true
}
28 changes: 26 additions & 2 deletions crates/vite_task_graph/run-config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
export type UserGlobalCacheConfig =
| boolean
| {
/**
* Enable caching for package.json scripts not defined in the `tasks` map.
*
* When `false`, package.json scripts will not be cached.
* When `true`, package.json scripts will be cached with default settings.
*
* Default: `false`
*/
scripts?: boolean;
/**
* Global cache kill switch for task entries.
*
* When `false`, overrides all tasks to disable caching, even tasks with `cache: true`.
* When `true`, respects each task's individual `cache` setting
* (each task's `cache` defaults to `true` if omitted).
*
* Default: `true`
*/
tasks?: boolean;
};

export type Task = {
/**
* The command to run for the task.
Expand Down Expand Up @@ -38,12 +62,12 @@ export type Task = {

export type RunConfig = {
/**
* Enable cache for all scripts from package.json.
* Root-level cache configuration.
*
* 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;
cache?: UserGlobalCacheConfig;
/**
* Task definitions
*/
Expand Down
5 changes: 4 additions & 1 deletion crates/vite_task_graph/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use std::sync::Arc;
use monostate::MustBe;
use rustc_hash::FxHashSet;
use serde::Serialize;
pub use user::{EnabledCacheConfig, UserCacheConfig, UserRunConfig, UserTaskConfig};
pub use user::{
EnabledCacheConfig, ResolvedGlobalCacheConfig, UserCacheConfig, UserGlobalCacheConfig,
UserRunConfig, UserTaskConfig,
};
use vite_path::AbsolutePath;
use vite_str::Str;

Expand Down
124 changes: 122 additions & 2 deletions crates/vite_task_graph/src/config/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,78 @@ pub struct UserTaskConfig {
pub options: UserTaskOptions,
}

/// Root-level cache configuration.
///
/// Controls caching behavior for the entire workspace.
///
/// - `true` is equivalent to `{ scripts: true, tasks: true }` — enables caching for both
/// package.json scripts and task entries.
/// - `false` is equivalent to `{ scripts: false, tasks: false }` — disables all caching.
/// - When omitted, defaults to `{ scripts: false, tasks: true }`.
///
/// 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.
#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
// TS derive macro generates code using std types that clippy disallows; skip derive during linting
#[cfg_attr(all(test, not(clippy)), derive(TS), ts(optional_fields))]
#[serde(untagged, deny_unknown_fields)]
pub enum UserGlobalCacheConfig {
Bool(bool),
/// Detailed cache configuration with separate control for scripts and tasks.
Detailed {
/// Enable caching for package.json scripts not defined in the `tasks` map.
///
/// When `false`, package.json scripts will not be cached.
/// When `true`, package.json scripts will be cached with default settings.
///
/// Default: `false`
scripts: Option<bool>,

/// Global cache kill switch for task entries.
///
/// When `false`, overrides all tasks to disable caching, even tasks with `cache: true`.
/// When `true`, respects each task's individual `cache` setting
/// (each task's `cache` defaults to `true` if omitted).
///
/// Default: `true`
tasks: Option<bool>,
},
}

/// Resolved global cache configuration with concrete boolean values.
pub struct ResolvedGlobalCacheConfig {
pub scripts: bool,
pub tasks: bool,
}

impl ResolvedGlobalCacheConfig {
/// Resolve from an optional user config, using defaults when `None`.
///
/// Default: `{ scripts: false, tasks: true }`
#[must_use]
pub fn resolve_from(config: Option<&UserGlobalCacheConfig>) -> Self {
match config {
None => Self { scripts: false, tasks: true },
Some(UserGlobalCacheConfig::Bool(true)) => Self { scripts: true, tasks: true },
Some(UserGlobalCacheConfig::Bool(false)) => Self { scripts: false, tasks: false },
Some(UserGlobalCacheConfig::Detailed { scripts, tasks }) => {
Self { scripts: scripts.unwrap_or(false), tasks: tasks.unwrap_or(true) }
}
}
}
}

/// User configuration structure for `run` field in `vite.config.*`
#[derive(Debug, Default, Deserialize)]
// TS derive macro generates code using std types that clippy disallows; skip derive during linting
#[cfg_attr(all(test, not(clippy)), derive(TS), ts(optional_fields, rename = "RunConfig"))]
#[serde(rename_all = "camelCase")]
pub struct UserRunConfig {
/// Enable cache for all scripts from package.json.
/// Root-level cache configuration.
///
/// 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>,
pub cache: Option<UserGlobalCacheConfig>,

/// Task definitions
pub tasks: Option<FxHashMap<Str, UserTaskConfig>>,
Expand Down Expand Up @@ -315,4 +376,63 @@ mod tests {
});
assert!(serde_json::from_value::<UserCacheConfig>(user_config_json).is_err());
}

#[test]
fn test_global_cache_bool_true() {
let config: UserGlobalCacheConfig = serde_json::from_value(json!(true)).unwrap();
assert_eq!(config, UserGlobalCacheConfig::Bool(true));
let resolved = ResolvedGlobalCacheConfig::resolve_from(Some(&config));
assert!(resolved.scripts);
assert!(resolved.tasks);
}

#[test]
fn test_global_cache_bool_false() {
let config: UserGlobalCacheConfig = serde_json::from_value(json!(false)).unwrap();
assert_eq!(config, UserGlobalCacheConfig::Bool(false));
let resolved = ResolvedGlobalCacheConfig::resolve_from(Some(&config));
assert!(!resolved.scripts);
assert!(!resolved.tasks);
}

#[test]
fn test_global_cache_detailed_scripts_only() {
let config: UserGlobalCacheConfig =
serde_json::from_value(json!({ "scripts": true })).unwrap();
let resolved = ResolvedGlobalCacheConfig::resolve_from(Some(&config));
assert!(resolved.scripts);
assert!(resolved.tasks); // defaults to true
}

#[test]
fn test_global_cache_detailed_tasks_false() {
let config: UserGlobalCacheConfig =
serde_json::from_value(json!({ "tasks": false })).unwrap();
let resolved = ResolvedGlobalCacheConfig::resolve_from(Some(&config));
assert!(!resolved.scripts); // defaults to false
assert!(!resolved.tasks);
}

#[test]
fn test_global_cache_detailed_both() {
let config: UserGlobalCacheConfig =
serde_json::from_value(json!({ "scripts": true, "tasks": false })).unwrap();
let resolved = ResolvedGlobalCacheConfig::resolve_from(Some(&config));
assert!(resolved.scripts);
assert!(!resolved.tasks);
}

#[test]
fn test_global_cache_none_defaults() {
let resolved = ResolvedGlobalCacheConfig::resolve_from(None);
assert!(!resolved.scripts); // defaults to false
assert!(resolved.tasks); // defaults to true
}

#[test]
fn test_global_cache_detailed_unknown_field() {
assert!(
serde_json::from_value::<UserGlobalCacheConfig>(json!({ "unknown": true })).is_err()
);
}
}
Loading
Loading