Skip to content

Commit 24baf0b

Browse files
branchseerclaude
andcommitted
refactor: rename ParsedCommand to Command and make resolved types internal
- Rename `ParsedCommand` → `Command` and `ParsedRunCommand` → `RunCommand` as the public API types - Rename old `Command` → `ResolvedCommand` and old `RunCommand` → `ResolvedRunCommand` as crate-internal types - `Session::main` and `HandledCommand::ViteTaskCommand` now accept `Command` directly (no `.into_command()` needed) - Fix summary message: `--verbose` → `--last-details` Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent cc00596 commit 24baf0b

26 files changed

Lines changed: 101 additions & 76 deletions

crates/vite_task/src/cli/mod.rs

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,78 +37,74 @@ pub struct RunFlags {
3737
}
3838

3939
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
40-
// Clap-parsed types (used only at the parsing boundary)
40+
// Public CLI types (clap-parsed)
4141
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
4242

4343
/// Arguments for the `run` subcommand as parsed by clap.
4444
///
4545
/// Contains the `--last-details` flag which is resolved into a separate
46-
/// [`Command::RunLastDetails`] variant via [`ParsedCommand::into_command`].
46+
/// [`ResolvedCommand::RunLastDetails`] variant via [`Command::into_resolved`].
4747
#[derive(Debug, clap::Args)]
48-
pub struct ParsedRunCommand {
48+
pub struct RunCommand {
4949
/// `packageName#taskName` or `taskName`. If omitted, lists all available tasks.
50-
task_specifier: Option<TaskSpecifier>,
50+
pub(crate) task_specifier: Option<TaskSpecifier>,
5151

5252
#[clap(flatten)]
53-
flags: RunFlags,
53+
pub(crate) flags: RunFlags,
5454

5555
/// Additional arguments to pass to the tasks
5656
#[clap(trailing_var_arg = true, allow_hyphen_values = true)]
57-
additional_args: Vec<Str>,
57+
pub(crate) additional_args: Vec<Str>,
5858

5959
/// Display the detailed summary of the last run.
6060
#[clap(long, exclusive = true)]
61-
last_details: bool,
61+
pub(crate) last_details: bool,
6262
}
6363

6464
/// vite task CLI subcommands as parsed by clap.
6565
///
66-
/// Use [`ParsedCommand::into_command`] to resolve into the dispatched [`Command`]
67-
/// enum, which makes `--last-details` exclusive at the type level.
66+
/// Pass directly to [`Session::main`] or [`HandledCommand::ViteTaskCommand`].
67+
/// The `--last-details` flag on the `run` subcommand is resolved internally.
6868
#[derive(Debug, Parser)]
69-
pub enum ParsedCommand {
69+
pub enum Command {
7070
/// Run tasks
71-
Run(ParsedRunCommand),
71+
Run(RunCommand),
7272
/// Manage the task cache
7373
Cache {
7474
#[clap(subcommand)]
7575
subcmd: CacheSubcommand,
7676
},
7777
}
7878

79-
impl ParsedCommand {
80-
/// Resolve the clap-parsed command into the dispatched [`Command`] enum.
79+
impl Command {
80+
/// Resolve the clap-parsed command into the dispatched [`ResolvedCommand`] enum.
8181
///
8282
/// When `--last-details` is set on the `run` subcommand, this produces
83-
/// [`Command::RunLastDetails`] instead of [`Command::Run`], making the
84-
/// exclusivity enforced at the type level.
83+
/// [`ResolvedCommand::RunLastDetails`] instead of [`ResolvedCommand::Run`],
84+
/// making the exclusivity enforced at the type level.
8585
#[must_use]
86-
pub fn into_command(self) -> Command {
86+
pub(crate) fn into_resolved(self) -> ResolvedCommand {
8787
match self {
88-
Self::Run(run) if run.last_details => Command::RunLastDetails,
89-
Self::Run(run) => Command::Run(RunCommand {
90-
task_specifier: run.task_specifier,
91-
flags: run.flags,
92-
additional_args: run.additional_args,
93-
}),
94-
Self::Cache { subcmd } => Command::Cache { subcmd },
88+
Self::Run(run) if run.last_details => ResolvedCommand::RunLastDetails,
89+
Self::Run(run) => ResolvedCommand::Run(run.into_resolved()),
90+
Self::Cache { subcmd } => ResolvedCommand::Cache { subcmd },
9591
}
9692
}
9793
}
9894

9995
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
100-
// Resolved types (used for dispatch — `--last-details` is a separate variant)
96+
// Internal resolved types (used for dispatch — `--last-details` is a separate variant)
10197
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
10298

103-
/// Resolved CLI command for dispatch.
99+
/// Resolved CLI command for internal dispatch.
104100
///
105-
/// Unlike [`ParsedCommand`], this enum makes `--last-details` a separate variant
106-
/// ([`Command::RunLastDetails`]) so that it is exclusive at the type level —
101+
/// Unlike [`Command`], this enum makes `--last-details` a separate variant
102+
/// ([`ResolvedCommand::RunLastDetails`]) so that it is exclusive at the type level —
107103
/// there is no way to combine it with task execution fields.
108104
#[derive(Debug)]
109-
pub enum Command {
105+
pub enum ResolvedCommand {
110106
/// Run tasks with the given parameters.
111-
Run(RunCommand),
107+
Run(ResolvedRunCommand),
112108
/// Display the saved detailed summary of the last run (`--last-details`).
113109
RunLastDetails,
114110
/// Manage the task cache.
@@ -118,9 +114,9 @@ pub enum Command {
118114
/// Resolved arguments for executing tasks.
119115
///
120116
/// Does not contain `last_details` — that case is represented by
121-
/// [`Command::RunLastDetails`] instead.
117+
/// [`ResolvedCommand::RunLastDetails`] instead.
122118
#[derive(Debug)]
123-
pub struct RunCommand {
119+
pub struct ResolvedRunCommand {
124120
/// `packageName#taskName` or `taskName`. If omitted, lists all available tasks.
125121
pub task_specifier: Option<TaskSpecifier>,
126122

@@ -130,6 +126,18 @@ pub struct RunCommand {
130126
pub additional_args: Vec<Str>,
131127
}
132128

129+
impl RunCommand {
130+
/// Convert to the resolved run command, stripping the `last_details` flag.
131+
#[must_use]
132+
pub(crate) fn into_resolved(self) -> ResolvedRunCommand {
133+
ResolvedRunCommand {
134+
task_specifier: self.task_specifier,
135+
flags: self.flags,
136+
additional_args: self.additional_args,
137+
}
138+
}
139+
}
140+
133141
#[derive(thiserror::Error, Debug)]
134142
pub enum CLITaskQueryError {
135143
#[error("no task specifier provided")]
@@ -142,7 +150,7 @@ pub enum CLITaskQueryError {
142150
PackageNameSpecifiedWithRecursive { package_name: Str, task_name: Str },
143151
}
144152

145-
impl RunCommand {
153+
impl ResolvedRunCommand {
146154
/// Convert to `QueryPlanRequest`, or return an error if invalid.
147155
///
148156
/// # Errors

crates/vite_task/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod maybe_str;
44
pub mod session;
55

66
// Public exports for vite_task_bin
7-
pub use cli::{CacheSubcommand, Command, ParsedCommand, RunCommand, RunFlags};
7+
pub use cli::{CacheSubcommand, Command, RunCommand, RunFlags};
88
pub use session::{CommandHandler, ExitStatus, HandledCommand, Session, SessionCallbacks};
99
pub use vite_task_graph::{
1010
config::{

crates/vite_task/src/session/mod.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use vite_task_plan::{
2929
};
3030
use vite_workspace::{WorkspaceRoot, find_workspace_root};
3131

32-
use crate::cli::{CacheSubcommand, Command, RunCommand, RunFlags};
32+
use crate::cli::{CacheSubcommand, Command, ResolvedCommand, RunCommand, RunFlags};
3333

3434
#[derive(Debug)]
3535
enum LazyTaskGraph<'a> {
@@ -100,13 +100,13 @@ impl vite_task_plan::PlanRequestParser for PlanRequestParser<'_> {
100100
) -> anyhow::Result<Option<PlanRequest>> {
101101
match self.command_handler.handle_command(command).await? {
102102
HandledCommand::Synthesized(synthetic) => Ok(Some(PlanRequest::Synthetic(synthetic))),
103-
HandledCommand::ViteTaskCommand(cli_command) => match cli_command {
104-
Command::Cache { .. } | Command::RunLastDetails => {
103+
HandledCommand::ViteTaskCommand(cli_command) => match cli_command.into_resolved() {
104+
ResolvedCommand::Cache { .. } | ResolvedCommand::RunLastDetails => {
105105
Ok(Some(PlanRequest::Synthetic(
106106
command.to_synthetic_plan_request(UserCacheConfig::disabled()),
107107
)))
108108
}
109-
Command::Run(run_command) => {
109+
ResolvedCommand::Run(run_command) => {
110110
match run_command.into_query_plan_request(&command.cwd) {
111111
Ok(query_plan_request) => Ok(Some(PlanRequest::Query(query_plan_request))),
112112
Err(crate::cli::CLITaskQueryError::MissingTaskSpecifier) => {
@@ -227,10 +227,10 @@ impl<'a> Session<'a> {
227227
reason = "session is single-threaded, futures do not need to be Send"
228228
)]
229229
pub async fn main(mut self, command: Command) -> anyhow::Result<ExitStatus> {
230-
match command {
231-
Command::Cache { ref subcmd } => self.handle_cache_command(subcmd),
232-
Command::RunLastDetails => self.show_last_run_details(),
233-
Command::Run(run_command) => {
230+
match command.into_resolved() {
231+
ResolvedCommand::Cache { ref subcmd } => self.handle_cache_command(subcmd),
232+
ResolvedCommand::RunLastDetails => self.show_last_run_details(),
233+
ResolvedCommand::Run(run_command) => {
234234
let cwd = Arc::clone(&self.cwd);
235235
let is_interactive =
236236
std::io::stdin().is_terminal() && std::io::stdout().is_terminal();
@@ -241,7 +241,7 @@ impl<'a> Session<'a> {
241241
let flags = run_command.flags;
242242
let additional_args = run_command.additional_args.clone();
243243

244-
match self.plan_from_cli_run(cwd, run_command).await {
244+
match self.plan_from_cli_run_resolved(cwd, run_command).await {
245245
Ok(ref graph) if graph.node_count() == 0 => {
246246
// No tasks matched the query — show task selector / "did you mean"
247247
self.handle_no_task(
@@ -399,8 +399,12 @@ impl<'a> Session<'a> {
399399
let selected_label = &select_items[selected_index].label;
400400
let task_specifier = TaskSpecifier::parse_raw(selected_label);
401401
let show_details = flags.verbose;
402-
let run_command =
403-
RunCommand { task_specifier: Some(task_specifier), flags, additional_args };
402+
let run_command = RunCommand {
403+
task_specifier: Some(task_specifier),
404+
flags,
405+
additional_args,
406+
last_details: false,
407+
};
404408

405409
let cwd = Arc::clone(&self.cwd);
406410
let graph = self.plan_from_cli_run(cwd, run_command).await?;
@@ -579,6 +583,19 @@ impl<'a> Session<'a> {
579583
&mut self,
580584
cwd: Arc<AbsolutePath>,
581585
command: RunCommand,
586+
) -> Result<ExecutionGraph, vite_task_plan::Error> {
587+
self.plan_from_cli_run_resolved(cwd, command.into_resolved()).await
588+
}
589+
590+
/// Internal: plans execution from a resolved run command.
591+
#[expect(
592+
clippy::future_not_send,
593+
reason = "session is single-threaded, futures do not need to be Send"
594+
)]
595+
async fn plan_from_cli_run_resolved(
596+
&mut self,
597+
cwd: Arc<AbsolutePath>,
598+
command: crate::cli::ResolvedRunCommand,
582599
) -> Result<ExecutionGraph, vite_task_plan::Error> {
583600
let query_plan_request = match command.into_query_plan_request(&cwd) {
584601
Ok(query_plan_request) => query_plan_request,

crates/vite_task/src/session/reporter/summary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ pub fn format_compact_summary(summary: &LastRunSummary) -> Vec<u8> {
709709
let _ = write!(
710710
buf,
711711
". {}",
712-
"(Run `vp run --verbose` for full details)".style(Style::new().bright_black()),
712+
"(Run `vp run --last-details` for full details)".style(Style::new().bright_black()),
713713
);
714714
let _ = writeln!(buf);
715715
}

crates/vite_task_bin/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_hash::FxHashMap;
1010
use vite_path::AbsolutePath;
1111
use vite_str::Str;
1212
use vite_task::{
13-
EnabledCacheConfig, HandledCommand, ParsedCommand, ScriptCommand, SessionCallbacks,
14-
UserCacheConfig, get_path_env, plan_request::SyntheticPlanRequest,
13+
Command, EnabledCacheConfig, HandledCommand, ScriptCommand, SessionCallbacks, UserCacheConfig,
14+
get_path_env, plan_request::SyntheticPlanRequest,
1515
};
1616

1717
#[derive(Debug, Default)]
@@ -85,7 +85,7 @@ pub enum Args {
8585
value: Str,
8686
},
8787
#[command(flatten)]
88-
Task(ParsedCommand),
88+
Task(Command),
8989
}
9090

9191
#[async_trait::async_trait(?Send)]
@@ -130,7 +130,7 @@ impl vite_task::CommandHandler for CommandHandler {
130130
envs: Arc::new(envs),
131131
}))
132132
}
133-
Args::Task(parsed) => Ok(HandledCommand::ViteTaskCommand(parsed.into_command())),
133+
Args::Task(parsed) => Ok(HandledCommand::ViteTaskCommand(parsed)),
134134
}
135135
}
136136
}

crates/vite_task_bin/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ async fn run() -> anyhow::Result<ExitStatus> {
2121
let mut owned_callbacks = OwnedSessionCallbacks::default();
2222
let session = Session::init(owned_callbacks.as_callbacks())?;
2323
match args {
24-
Args::Task(parsed) => session.main(parsed.into_command()).await,
24+
Args::Task(parsed) => session.main(parsed).await,
2525
args => {
2626
// If env FOO is set, run `print-env FOO` via Session::exec before proceeding.
2727
// In vite-plus, Session::exec is used for auto-install.

crates/vite_task_bin/tests/e2e_snapshots/fixtures/cache-miss-command-change/snapshots/cache miss command change.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ $ print bar
1010
bar
1111

1212
---
13-
[vp run] 0/2 cache hit (0%). (Run `vp run --verbose` for full details)
13+
[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details)
1414
> json-edit package.json '_.scripts.task = "print baz && print bar"' # change first subtask
1515

1616
> vp run task # first: cache miss, second: cache hit
@@ -21,7 +21,7 @@ $ print bar ✓ cache hit, replaying
2121
bar
2222

2323
---
24-
[vp run] 1/2 cache hit (50%), <duration> saved. (Run `vp run --verbose` for full details)
24+
[vp run] 1/2 cache hit (50%), <duration> saved. (Run `vp run --last-details` for full details)
2525
> json-edit package.json '_.scripts.task = "print bar"' # remove first subtask
2626

2727
> vp run task # cache hit

crates/vite_task_bin/tests/e2e_snapshots/fixtures/exit-codes/snapshots/multiple task failures returns exit code 1.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ expression: e2e_outputs
88
~/packages/pkg-b$ node -e "process.exit(7)"
99

1010
---
11-
[vp run] 0/2 cache hit (0%), 2 failed. (Run `vp run --verbose` for full details)
11+
[vp run] 0/2 cache hit (0%), 2 failed. (Run `vp run --last-details` for full details)

crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdin-inheritance/snapshots/multiple tasks get null stdin.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ expression: e2e_outputs
88
$ read-stdincache disabled: no cache config
99

1010
---
11-
[vp run] 0/2 cache hit (0%). (Run `vp run --verbose` for full details)
11+
[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details)

crates/vite_task_bin/tests/e2e_snapshots/fixtures/stdio-detection/snapshots/multiple tasks, cache disabled.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ stdout:not-tty
1414
stderr:not-tty
1515

1616
---
17-
[vp run] 0/2 cache hit (0%). (Run `vp run --verbose` for full details)
17+
[vp run] 0/2 cache hit (0%). (Run `vp run --last-details` for full details)

0 commit comments

Comments
 (0)