diff --git a/crates/turborepo-lib/src/cli/mod.rs b/crates/turborepo-lib/src/cli/mod.rs index fc14a368e0d2d..56a939d9a45e2 100644 --- a/crates/turborepo-lib/src/cli/mod.rs +++ b/crates/turborepo-lib/src/cli/mod.rs @@ -606,6 +606,9 @@ pub enum Command { /// GraphQL server with GraphiQL. #[clap(hide = true)] Query { + /// Pass variables to the query via a JSON file + #[clap(short = 'V', long, requires = "query")] + variables: Option, /// The query to run, either a file path or a query string query: Option, }, @@ -1343,14 +1346,16 @@ pub async fn run( })?; Ok(exit_code) } - Command::Query { query } => { + Command::Query { query, variables } => { warn!("query command is experimental and may change in the future"); let query = query.clone(); + let variables = variables.clone(); let event = CommandEventBuilder::new("query").with_parent(&root_telemetry); event.track_call(); + let base = CommandBase::new(cli_args, repo_root, version, color_config); - let query = query::run(base, event, query).await?; + let query = query::run(base, event, query, variables.as_deref()).await?; Ok(query) } diff --git a/crates/turborepo-lib/src/commands/query.rs b/crates/turborepo-lib/src/commands/query.rs index 6d367bd562688..24fac3e27e66c 100644 --- a/crates/turborepo-lib/src/commands/query.rs +++ b/crates/turborepo-lib/src/commands/query.rs @@ -1,6 +1,7 @@ use std::{fs, sync::Arc}; -use async_graphql::{EmptyMutation, EmptySubscription, Schema, ServerError}; +use async_graphql::{EmptyMutation, EmptySubscription, Request, Schema, ServerError, Variables}; +use camino::Utf8Path; use miette::{Diagnostic, Report, SourceSpan}; use thiserror::Error; use turbopath::AbsoluteSystemPathBuf; @@ -58,6 +59,7 @@ pub async fn run( mut base: CommandBase, telemetry: CommandEventBuilder, query: Option, + variables_path: Option<&Utf8Path>, ) -> Result { let signal = get_signal()?; let handler = SignalHandler::new(signal); @@ -92,7 +94,18 @@ pub async fn run( EmptySubscription, ); - let result = schema.execute(&query).await; + let variables: Variables = variables_path + .map(AbsoluteSystemPathBuf::from_cwd) + .transpose()? + .map(|path| path.read_to_string()) + .transpose()? + .map(|content| serde_json::from_str(&content)) + .transpose()? + .unwrap_or_default(); + + let request = Request::new(&query).variables(variables); + + let result = schema.execute(request).await; if result.errors.is_empty() { println!("{}", serde_json::to_string_pretty(&result)?); } else { diff --git a/turborepo-tests/integration/tests/query/variables.t b/turborepo-tests/integration/tests/query/variables.t new file mode 100644 index 0000000000000..c51caeb9a34c6 --- /dev/null +++ b/turborepo-tests/integration/tests/query/variables.t @@ -0,0 +1,44 @@ +Setup + $ . ${TESTDIR}/../../../helpers/setup_integration_test.sh + +Create a variables file + $ echo '{ "name": "my-app" }' > vars.json + +Query packages + $ ${TURBO} query 'query($name: String) { package(name: $name) { name } }' --variables vars.json | jq + WARNING query command is experimental and may change in the future + { + "data": { + "package": { + "name": "my-app" + } + } + } + +Write query to file + $ echo 'query($name: String) { package(name: $name) { name } }' > query.gql + +Run the query + $ ${TURBO} query query.gql --variables vars.json | jq + WARNING query command is experimental and may change in the future + { + "data": { + "package": { + "name": "my-app" + } + } + } + +Make sure we can't pass variables without a query + $ ${TURBO} query --variables vars.json + ERROR the following required arguments were not provided: + + + Usage: turbo(.exe)? query --variables (re) + + For more information, try '--help'. + + [1] + + +