From 13749409cd15db2ac0143dc7e4473d9f2b303fc9 Mon Sep 17 00:00:00 2001 From: David Culbreth Date: Wed, 4 Mar 2026 23:44:45 -0600 Subject: [PATCH] making linters happy --- crates/api/src/dto/history.rs | 2 +- crates/api/src/routes/actions.rs | 5 +- crates/api/src/routes/artifacts.rs | 4 +- crates/api/src/routes/auth.rs | 5 +- crates/api/src/routes/keys.rs | 5 +- crates/api/src/routes/packs.rs | 15 +- crates/api/src/routes/rules.rs | 5 +- crates/api/src/routes/triggers.rs | 10 +- crates/api/src/routes/webhooks.rs | 2 + crates/api/src/routes/workflows.rs | 21 +- crates/api/tests/helpers.rs | 4 +- crates/api/tests/pack_workflow_tests.rs | 8 +- crates/api/tests/workflow_tests.rs | 2 +- crates/cli/src/client.rs | 15 +- crates/cli/src/commands/action.rs | 22 +- crates/cli/src/commands/execution.rs | 1 + crates/cli/src/commands/pack.rs | 87 +++--- crates/cli/src/commands/pack_index.rs | 20 +- crates/cli/src/commands/rule.rs | 2 + crates/cli/src/wait.rs | 2 +- crates/cli/tests/pack_registry_tests.rs | 4 +- crates/common/src/auth/jwt.rs | 15 +- crates/common/src/models.rs | 53 +--- crates/common/src/mq/message_queue.rs | 2 +- crates/common/src/mq/mod.rs | 27 +- crates/common/src/pack_environment.rs | 46 ++- crates/common/src/pack_registry/dependency.rs | 56 ++-- crates/common/src/pack_registry/installer.rs | 8 +- crates/common/src/pack_registry/loader.rs | 38 ++- crates/common/src/pack_registry/mod.rs | 5 - crates/common/src/repositories/action.rs | 3 +- .../common/src/repositories/entity_history.rs | 2 +- crates/common/src/repositories/event.rs | 2 +- crates/common/src/repositories/execution.rs | 2 +- crates/common/src/repositories/identity.rs | 2 +- crates/common/src/repositories/inquiry.rs | 2 +- crates/common/src/repositories/key.rs | 2 +- crates/common/src/repositories/pack.rs | 1 + .../src/repositories/runtime_version.rs | 2 +- crates/common/src/repositories/trigger.rs | 2 +- crates/common/src/runtime_detection.rs | 13 +- crates/common/src/test_executor.rs | 5 +- .../src/workflow/expression/evaluator.rs | 6 +- crates/common/src/workflow/expression/mod.rs | 4 +- .../src/workflow/expression/tokenizer.rs | 4 +- crates/common/src/workflow/loader.rs | 12 +- crates/common/src/workflow/parser.rs | 4 +- crates/common/src/workflow/registrar.rs | 12 +- crates/common/src/workflow/validator.rs | 4 +- .../tests/execution_repository_tests.rs | 2 +- crates/common/tests/key_repository_tests.rs | 20 +- .../common/tests/repository_worker_tests.rs | 2 +- crates/common/tests/rule_repository_tests.rs | 8 +- .../common/tests/sensor_repository_tests.rs | 10 +- .../common/tests/trigger_repository_tests.rs | 6 +- crates/core-timer-sensor/src/timer_manager.rs | 2 +- crates/core-timer-sensor/src/types.rs | 1 + crates/executor/src/completion_listener.rs | 13 +- crates/executor/src/dead_letter_handler.rs | 3 +- crates/executor/src/event_processor.rs | 6 +- crates/executor/src/execution_manager.rs | 1 - crates/executor/src/policy_enforcer.rs | 13 +- crates/executor/src/scheduler.rs | 39 +-- crates/executor/src/worker_health.rs | 2 +- crates/executor/src/workflow/context.rs | 4 +- crates/executor/src/workflow/graph.rs | 4 +- crates/sensor/src/sensor_manager.rs | 13 +- crates/worker/src/env_setup.rs | 14 +- crates/worker/src/executor.rs | 23 +- crates/worker/src/registration.rs | 6 +- crates/worker/src/runtime/native.rs | 1 + .../worker/src/runtime/parameter_passing.rs | 10 +- crates/worker/src/runtime/process_executor.rs | 1 + crates/worker/src/runtime/shell.rs | 2 + crates/worker/src/secrets.rs | 2 +- crates/worker/src/service.rs | 3 +- crates/worker/src/version_verify.rs | 2 +- web/knip.json | 2 +- web/package-lock.json | 272 ++++++++---------- web/package.json | 3 +- web/src/main.tsx | 2 +- 81 files changed, 468 insertions(+), 599 deletions(-) diff --git a/crates/api/src/dto/history.rs b/crates/api/src/dto/history.rs index b468297..2c3b412 100644 --- a/crates/api/src/dto/history.rs +++ b/crates/api/src/dto/history.rs @@ -107,7 +107,7 @@ impl HistoryQueryParams { pub fn to_repo_params( &self, ) -> attune_common::repositories::entity_history::HistoryQueryParams { - let limit = (self.page_size.min(1000).max(1)) as i64; + let limit = (self.page_size.clamp(1, 1000)) as i64; let offset = ((self.page.saturating_sub(1)) as i64) * limit; attune_common::repositories::entity_history::HistoryQueryParams { diff --git a/crates/api/src/routes/actions.rs b/crates/api/src/routes/actions.rs index 6e49e11..b8c94c1 100644 --- a/crates/api/src/routes/actions.rs +++ b/crates/api/src/routes/actions.rs @@ -160,7 +160,10 @@ pub async fn create_action( request.validate()?; // Check if action with same ref already exists - if let Some(_) = ActionRepository::find_by_ref(&state.db, &request.r#ref).await? { + if ActionRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Action with ref '{}' already exists", request.r#ref diff --git a/crates/api/src/routes/artifacts.rs b/crates/api/src/routes/artifacts.rs index cf15690..5424186 100644 --- a/crates/api/src/routes/artifacts.rs +++ b/crates/api/src/routes/artifacts.rs @@ -1877,7 +1877,7 @@ pub async fn stream_artifact( Some(( Ok(Event::default() .event("content") - .data(String::from_utf8_lossy(&buf).into_owned())), + .data(String::from_utf8_lossy(&buf))), TailState::Tailing { full_path, file_path, @@ -1967,7 +1967,7 @@ pub async fn stream_artifact( Some(( Ok(Event::default() .event("append") - .data(String::from_utf8_lossy(&new_buf).into_owned())), + .data(String::from_utf8_lossy(&new_buf))), TailState::Tailing { full_path, file_path, diff --git a/crates/api/src/routes/auth.rs b/crates/api/src/routes/auth.rs index 4f11188..94ba402 100644 --- a/crates/api/src/routes/auth.rs +++ b/crates/api/src/routes/auth.rs @@ -158,7 +158,10 @@ pub async fn register( .map_err(|e| ApiError::ValidationError(format!("Invalid registration request: {}", e)))?; // Check if login already exists - if let Some(_) = IdentityRepository::find_by_login(&state.db, &payload.login).await? { + if IdentityRepository::find_by_login(&state.db, &payload.login) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Identity with login '{}' already exists", payload.login diff --git a/crates/api/src/routes/keys.rs b/crates/api/src/routes/keys.rs index 7163072..4ded5c8 100644 --- a/crates/api/src/routes/keys.rs +++ b/crates/api/src/routes/keys.rs @@ -138,7 +138,10 @@ pub async fn create_key( request.validate()?; // Check if key with same ref already exists - if let Some(_) = KeyRepository::find_by_ref(&state.db, &request.r#ref).await? { + if KeyRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Key with ref '{}' already exists", request.r#ref diff --git a/crates/api/src/routes/packs.rs b/crates/api/src/routes/packs.rs index 6fb0a74..3b286c2 100644 --- a/crates/api/src/routes/packs.rs +++ b/crates/api/src/routes/packs.rs @@ -585,10 +585,9 @@ pub async fn upload_pack( skip_tests, ) .await - .map_err(|e| { + .inspect_err(|_e| { // Clean up permanent storage on failure let _ = std::fs::remove_dir_all(&final_path); - e })?; // Fetch the registered pack @@ -947,8 +946,8 @@ async fn register_pack_internal( // a best-effort optimisation for non-Docker (bare-metal) setups // where the API host has the interpreter available. if let Some(ref env_cfg) = exec_config.environment { - if env_cfg.env_type != "none" { - if !env_dir.exists() && !env_cfg.create_command.is_empty() { + if env_cfg.env_type != "none" + && !env_dir.exists() && !env_cfg.create_command.is_empty() { // Ensure parent directories exist if let Some(parent) = env_dir.parent() { let _ = std::fs::create_dir_all(parent); @@ -1002,7 +1001,6 @@ async fn register_pack_internal( } } } - } } // Attempt to install dependencies if manifest file exists. @@ -1107,9 +1105,7 @@ async fn register_pack_internal( if is_new_pack { let _ = PackRepository::delete(&state.db, pack.id).await; } - return Err(ApiError::BadRequest(format!( - "Pack registration failed: tests did not pass. Use force=true to register anyway." - ))); + return Err(ApiError::BadRequest("Pack registration failed: tests did not pass. Use force=true to register anyway.".to_string())); } if !test_passed && force { @@ -1359,10 +1355,9 @@ pub async fn install_pack( request.skip_tests, ) .await - .map_err(|e| { + .inspect_err(|_e| { // Clean up the permanent storage if registration fails let _ = std::fs::remove_dir_all(&final_path); - e })?; // Fetch the registered pack diff --git a/crates/api/src/routes/rules.rs b/crates/api/src/routes/rules.rs index bb08ac6..a57f017 100644 --- a/crates/api/src/routes/rules.rs +++ b/crates/api/src/routes/rules.rs @@ -290,7 +290,10 @@ pub async fn create_rule( request.validate()?; // Check if rule with same ref already exists - if let Some(_) = RuleRepository::find_by_ref(&state.db, &request.r#ref).await? { + if RuleRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Rule with ref '{}' already exists", request.r#ref diff --git a/crates/api/src/routes/triggers.rs b/crates/api/src/routes/triggers.rs index fe96590..f6a082a 100644 --- a/crates/api/src/routes/triggers.rs +++ b/crates/api/src/routes/triggers.rs @@ -198,7 +198,10 @@ pub async fn create_trigger( request.validate()?; // Check if trigger with same ref already exists - if let Some(_) = TriggerRepository::find_by_ref(&state.db, &request.r#ref).await? { + if TriggerRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Trigger with ref '{}' already exists", request.r#ref @@ -623,7 +626,10 @@ pub async fn create_sensor( request.validate()?; // Check if sensor with same ref already exists - if let Some(_) = SensorRepository::find_by_ref(&state.db, &request.r#ref).await? { + if SensorRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Sensor with ref '{}' already exists", request.r#ref diff --git a/crates/api/src/routes/webhooks.rs b/crates/api/src/routes/webhooks.rs index b800105..e318a9e 100644 --- a/crates/api/src/routes/webhooks.rs +++ b/crates/api/src/routes/webhooks.rs @@ -714,6 +714,7 @@ pub async fn receive_webhook( } // Helper function to log webhook events +#[allow(clippy::too_many_arguments)] async fn log_webhook_event( state: &AppState, trigger: &attune_common::models::trigger::Trigger, @@ -753,6 +754,7 @@ async fn log_webhook_event( } // Helper function to log failures when trigger is not found +#[allow(clippy::too_many_arguments)] async fn log_webhook_failure( _state: &AppState, webhook_key: String, diff --git a/crates/api/src/routes/workflows.rs b/crates/api/src/routes/workflows.rs index 7f56255..4e5dd05 100644 --- a/crates/api/src/routes/workflows.rs +++ b/crates/api/src/routes/workflows.rs @@ -181,7 +181,10 @@ pub async fn create_workflow( request.validate()?; // Check if workflow with same ref already exists - if let Some(_) = WorkflowDefinitionRepository::find_by_ref(&state.db, &request.r#ref).await? { + if WorkflowDefinitionRepository::find_by_ref(&state.db, &request.r#ref) + .await? + .is_some() + { return Err(ApiError::Conflict(format!( "Workflow with ref '{}' already exists", request.r#ref @@ -519,7 +522,7 @@ pub async fn update_workflow_file( /// Write a workflow definition to disk as YAML async fn write_workflow_yaml( - packs_base_dir: &PathBuf, + packs_base_dir: &std::path::Path, pack_ref: &str, request: &SaveWorkflowFileRequest, ) -> Result<(), ApiError> { @@ -630,9 +633,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin "# Action definition for workflow {}.{}", pack_ref, request.name )); - lines.push(format!( - "# The workflow graph (tasks, transitions, variables) is in:" - )); + lines.push("# The workflow graph (tasks, transitions, variables) is in:".to_string()); lines.push(format!( "# actions/workflows/{}.workflow.yaml", request.name @@ -646,7 +647,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin lines.push(format!("description: \"{}\"", desc.replace('"', "\\\""))); } } - lines.push(format!("enabled: true")); + lines.push("enabled: true".to_string()); lines.push(format!( "workflow_file: workflows/{}.workflow.yaml", request.name @@ -658,7 +659,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin if !obj.is_empty() { lines.push(String::new()); let params_yaml = serde_yaml_ng::to_string(params).unwrap_or_default(); - lines.push(format!("parameters:")); + lines.push("parameters:".to_string()); // Indent the YAML output under `parameters:` for line in params_yaml.lines() { lines.push(format!(" {}", line)); @@ -673,7 +674,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin if !obj.is_empty() { lines.push(String::new()); let output_yaml = serde_yaml_ng::to_string(output).unwrap_or_default(); - lines.push(format!("output:")); + lines.push("output:".to_string()); for line in output_yaml.lines() { lines.push(format!(" {}", line)); } @@ -685,7 +686,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin if let Some(ref tags) = request.tags { if !tags.is_empty() { lines.push(String::new()); - lines.push(format!("tags:")); + lines.push("tags:".to_string()); for tag in tags { lines.push(format!(" - {}", tag)); } @@ -701,6 +702,7 @@ fn build_action_yaml(pack_ref: &str, request: &SaveWorkflowFileRequest) -> Strin /// This ensures the workflow appears in action lists and the action palette in the /// workflow builder. The action is linked to the workflow definition via the /// `workflow_def` FK. +#[allow(clippy::too_many_arguments)] async fn create_companion_action( db: &sqlx::PgPool, workflow_ref: &str, @@ -835,6 +837,7 @@ async fn update_companion_action( /// /// If the action already exists, update it. If it doesn't exist (e.g., for workflows /// created before the companion-action fix), create it. +#[allow(clippy::too_many_arguments)] async fn ensure_companion_action( db: &sqlx::PgPool, workflow_def_id: i64, diff --git a/crates/api/tests/helpers.rs b/crates/api/tests/helpers.rs index aa6d1e8..d90dded 100644 --- a/crates/api/tests/helpers.rs +++ b/crates/api/tests/helpers.rs @@ -362,11 +362,11 @@ impl Drop for TestContext { let test_packs_dir = self.test_packs_dir.clone(); // Spawn cleanup task in background - let _ = tokio::spawn(async move { + drop(tokio::spawn(async move { if let Err(e) = cleanup_test_schema(&schema).await { eprintln!("Failed to cleanup test schema {}: {}", schema, e); } - }); + })); // Cleanup the test packs directory synchronously let _ = std::fs::remove_dir_all(&test_packs_dir); diff --git a/crates/api/tests/pack_workflow_tests.rs b/crates/api/tests/pack_workflow_tests.rs index adb8a6c..2fac287 100644 --- a/crates/api/tests/pack_workflow_tests.rs +++ b/crates/api/tests/pack_workflow_tests.rs @@ -64,7 +64,7 @@ async fn test_sync_pack_workflows_endpoint() { // Use unique pack name to avoid conflicts in parallel tests let pack_name = format!( "test_pack_{}", - uuid::Uuid::new_v4().to_string().replace("-", "")[..8].to_string() + &uuid::Uuid::new_v4().to_string().replace("-", "")[..8] ); // Create temporary directory for pack workflows @@ -100,7 +100,7 @@ async fn test_validate_pack_workflows_endpoint() { // Use unique pack name to avoid conflicts in parallel tests let pack_name = format!( "test_pack_{}", - uuid::Uuid::new_v4().to_string().replace("-", "")[..8].to_string() + &uuid::Uuid::new_v4().to_string().replace("-", "")[..8] ); // Create pack in database @@ -158,7 +158,7 @@ async fn test_sync_workflows_requires_authentication() { // Use unique pack name to avoid conflicts in parallel tests let pack_name = format!( "test_pack_{}", - uuid::Uuid::new_v4().to_string().replace("-", "")[..8].to_string() + &uuid::Uuid::new_v4().to_string().replace("-", "")[..8] ); // Create pack in database @@ -185,7 +185,7 @@ async fn test_validate_workflows_requires_authentication() { // Use unique pack name to avoid conflicts in parallel tests let pack_name = format!( "test_pack_{}", - uuid::Uuid::new_v4().to_string().replace("-", "")[..8].to_string() + &uuid::Uuid::new_v4().to_string().replace("-", "")[..8] ); // Create pack in database diff --git a/crates/api/tests/workflow_tests.rs b/crates/api/tests/workflow_tests.rs index 8048afe..517821f 100644 --- a/crates/api/tests/workflow_tests.rs +++ b/crates/api/tests/workflow_tests.rs @@ -14,7 +14,7 @@ use helpers::*; fn unique_pack_name() -> String { format!( "test_pack_{}", - uuid::Uuid::new_v4().to_string().replace("-", "")[..8].to_string() + &uuid::Uuid::new_v4().to_string().replace("-", "")[..8] ) } diff --git a/crates/cli/src/client.rs b/crates/cli/src/client.rs index 0c7c36e..17a363b 100644 --- a/crates/cli/src/client.rs +++ b/crates/cli/src/client.rs @@ -180,8 +180,8 @@ impl ApiClient { let req = self.attach_body(self.build_request(method.clone(), path), body); let response = req.send().await.context("Failed to send request to API")?; - if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() { - if self.refresh_auth_token().await? { + if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() + && self.refresh_auth_token().await? { // Retry with new token let req = self.attach_body(self.build_request(method, path), body); let response = req @@ -190,7 +190,6 @@ impl ApiClient { .context("Failed to send request to API (retry)")?; return self.handle_response(response).await; } - } self.handle_response(response).await } @@ -205,8 +204,8 @@ impl ApiClient { let req = self.attach_body(self.build_request(method.clone(), path), body); let response = req.send().await.context("Failed to send request to API")?; - if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() { - if self.refresh_auth_token().await? { + if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() + && self.refresh_auth_token().await? { let req = self.attach_body(self.build_request(method, path), body); let response = req .send() @@ -214,7 +213,6 @@ impl ApiClient { .context("Failed to send request to API (retry)")?; return self.handle_empty_response(response).await; } - } self.handle_empty_response(response).await } @@ -393,8 +391,8 @@ impl ApiClient { .await .context("Failed to send multipart request to API")?; - if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() { - if self.refresh_auth_token().await? { + if response.status() == StatusCode::UNAUTHORIZED && self.refresh_token.is_some() + && self.refresh_auth_token().await? { // Retry with new token let req = build_multipart_request(self, &file_bytes)?; let response = req @@ -403,7 +401,6 @@ impl ApiClient { .context("Failed to send multipart request to API (retry)")?; return self.handle_response(response).await; } - } self.handle_response(response).await } diff --git a/crates/cli/src/commands/action.rs b/crates/cli/src/commands/action.rs index 2781871..a5c6d0a 100644 --- a/crates/cli/src/commands/action.rs +++ b/crates/cli/src/commands/action.rs @@ -314,6 +314,7 @@ async fn handle_show( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_update( action_ref: String, label: Option, @@ -415,6 +416,7 @@ async fn handle_delete( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_execute( action_ref: String, params: Vec, @@ -454,11 +456,8 @@ async fn handle_execute( parameters, }; - match output_format { - OutputFormat::Table => { - output::print_info(&format!("Executing action: {}", action_ref)); - } - _ => {} + if output_format == OutputFormat::Table { + output::print_info(&format!("Executing action: {}", action_ref)); } let path = "/executions/execute".to_string(); @@ -481,14 +480,11 @@ async fn handle_execute( return Ok(()); } - match output_format { - OutputFormat::Table => { - output::print_info(&format!( - "Waiting for execution {} to complete...", - execution.id - )); - } - _ => {} + if output_format == OutputFormat::Table { + output::print_info(&format!( + "Waiting for execution {} to complete...", + execution.id + )); } let verbose = matches!(output_format, OutputFormat::Table); diff --git a/crates/cli/src/commands/execution.rs b/crates/cli/src/commands/execution.rs index c12047f..cb395c1 100644 --- a/crates/cli/src/commands/execution.rs +++ b/crates/cli/src/commands/execution.rs @@ -163,6 +163,7 @@ pub async fn handle_execution_command( } } +#[allow(clippy::too_many_arguments)] async fn handle_list( profile: &Option, pack: Option, diff --git a/crates/cli/src/commands/pack.rs b/crates/cli/src/commands/pack.rs index 921b322..89677a0 100644 --- a/crates/cli/src/commands/pack.rs +++ b/crates/cli/src/commands/pack.rs @@ -468,7 +468,7 @@ pub async fn handle_pack_command( /// /// Splits on `_`, `-`, or `.` and title-cases each word. fn label_from_ref(r: &str) -> String { - r.split(|c| c == '_' || c == '-' || c == '.') + r.split(['_', '-', '.']) .filter(|s| !s.is_empty()) .map(|word| { let mut chars = word.chars(); @@ -484,6 +484,7 @@ fn label_from_ref(r: &str) -> String { .join(" ") } +#[allow(clippy::too_many_arguments)] async fn handle_create( profile: &Option, ref_flag: Option, @@ -725,6 +726,7 @@ async fn handle_show( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_install( profile: &Option, source: String, @@ -742,18 +744,15 @@ async fn handle_install( // Detect source type let source_type = detect_source_type(&source, ref_spec.as_deref(), no_registry); - match output_format { - OutputFormat::Table => { - output::print_info(&format!( - "Installing pack from: {} ({})", - source, source_type - )); - output::print_info("Starting installation..."); - if skip_deps { - output::print_info("โš  Dependency validation will be skipped"); - } + if output_format == OutputFormat::Table { + output::print_info(&format!( + "Installing pack from: {} ({})", + source, source_type + )); + output::print_info("Starting installation..."); + if skip_deps { + output::print_info("โš  Dependency validation will be skipped"); } - _ => {} } let request = InstallPackRequest { @@ -880,12 +879,9 @@ async fn handle_upload( .and_then(|v| v.as_str()) .unwrap_or("unknown"); - match output_format { - OutputFormat::Table => { - output::print_info(&format!("Uploading pack '{}' from: {}", pack_ref, path)); - output::print_info("Creating archive..."); - } - _ => {} + if output_format == OutputFormat::Table { + output::print_info(&format!("Uploading pack '{}' from: {}", pack_ref, path)); + output::print_info("Creating archive..."); } // Build an in-memory tar.gz of the pack directory @@ -908,14 +904,11 @@ async fn handle_upload( let archive_size_kb = tar_gz_bytes.len() / 1024; - match output_format { - OutputFormat::Table => { - output::print_info(&format!( - "Archive ready ({} KB), uploading...", - archive_size_kb - )); - } - _ => {} + if output_format == OutputFormat::Table { + output::print_info(&format!( + "Archive ready ({} KB), uploading...", + archive_size_kb + )); } let config = CliConfig::load_with_profile(profile.as_deref())?; @@ -1014,25 +1007,17 @@ async fn handle_register( && !path.starts_with("/app/") && !path.starts_with("/packs"); if looks_local { - match output_format { - OutputFormat::Table => { - output::print_info(&format!("Registering pack from: {}", path)); - eprintln!( - "โš  Warning: '{}' looks like a local path. If the API is running in \ - Docker it may not be able to access this path.\n \ - Use `attune pack upload {}` instead to upload the pack directly.", - path, path - ); - } - _ => {} - } - } else { - match output_format { - OutputFormat::Table => { - output::print_info(&format!("Registering pack from: {}", path)); - } - _ => {} + if output_format == OutputFormat::Table { + output::print_info(&format!("Registering pack from: {}", path)); + eprintln!( + "โš  Warning: '{}' looks like a local path. If the API is running in \ + Docker it may not be able to access this path.\n \ + Use `attune pack upload {}` instead to upload the pack directly.", + path, path + ); } + } else if output_format == OutputFormat::Table { + output::print_info(&format!("Registering pack from: {}", path)); } let request = RegisterPackRequest { @@ -1173,13 +1158,10 @@ async fn handle_test( let executor = TestExecutor::new(pack_base_dir); // Print test start message - match output_format { - OutputFormat::Table => { - println!(); - output::print_section(&format!("๐Ÿงช Testing Pack: {} v{}", pack_ref, pack_version)); - println!(); - } - _ => {} + if output_format == OutputFormat::Table { + println!(); + output::print_section(&format!("๐Ÿงช Testing Pack: {} v{}", pack_ref, pack_version)); + println!(); } // Execute tests @@ -1688,7 +1670,7 @@ async fn handle_index_entry( if let Some(ref git) = git_url { let default_ref = format!("v{}", version); - let ref_value = git_ref.as_ref().map(|s| s.as_str()).unwrap_or(&default_ref); + let ref_value = git_ref.as_deref().unwrap_or(&default_ref); let git_source = serde_json::json!({ "type": "git", "url": git, @@ -1790,6 +1772,7 @@ async fn handle_index_entry( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_update( profile: &Option, pack_ref: String, diff --git a/crates/cli/src/commands/pack_index.rs b/crates/cli/src/commands/pack_index.rs index 3a6a717..d03a3e1 100644 --- a/crates/cli/src/commands/pack_index.rs +++ b/crates/cli/src/commands/pack_index.rs @@ -76,10 +76,8 @@ pub async fn handle_index_update( if output_format == OutputFormat::Table { output::print_info(&format!("Updating existing entry for '{}'", pack_ref)); } - } else { - if output_format == OutputFormat::Table { - output::print_info(&format!("Adding new entry for '{}'", pack_ref)); - } + } else if output_format == OutputFormat::Table { + output::print_info(&format!("Adding new entry for '{}'", pack_ref)); } // Calculate checksum @@ -93,7 +91,7 @@ pub async fn handle_index_update( if let Some(ref git) = git_url { let default_ref = format!("v{}", version); - let ref_value = git_ref.as_ref().map(|s| s.as_str()).unwrap_or(&default_ref); + let ref_value = git_ref.as_deref().unwrap_or(&default_ref); install_sources.push(serde_json::json!({ "type": "git", "url": git, @@ -318,13 +316,11 @@ pub async fn handle_index_merge( )); } packs_map.insert(pack_ref.to_string(), pack.clone()); - } else { - if output_format == OutputFormat::Table { - output::print_info(&format!( - " Keeping '{}' at {} (newer than {})", - pack_ref, existing_version, new_version - )); - } + } else if output_format == OutputFormat::Table { + output::print_info(&format!( + " Keeping '{}' at {} (newer than {})", + pack_ref, existing_version, new_version + )); } duplicates_resolved += 1; } else { diff --git a/crates/cli/src/commands/rule.rs b/crates/cli/src/commands/rule.rs index 39f28f1..5f7e2b5 100644 --- a/crates/cli/src/commands/rule.rs +++ b/crates/cli/src/commands/rule.rs @@ -354,6 +354,7 @@ async fn handle_show( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_update( profile: &Option, rule_ref: String, @@ -477,6 +478,7 @@ async fn handle_toggle( Ok(()) } +#[allow(clippy::too_many_arguments)] async fn handle_create( profile: &Option, name: String, diff --git a/crates/cli/src/wait.rs b/crates/cli/src/wait.rs index 38af948..7e05f9e 100644 --- a/crates/cli/src/wait.rs +++ b/crates/cli/src/wait.rs @@ -472,7 +472,7 @@ fn resolve_ws_url(opts: &WaitOptions<'_>) -> Option { let api_url = opts.api_client.base_url(); // Transform http(s)://host:PORT/... โ†’ ws(s)://host:8081 - let ws_url = derive_notifier_url(&api_url)?; + let ws_url = derive_notifier_url(api_url)?; Some(ws_url) } diff --git a/crates/cli/tests/pack_registry_tests.rs b/crates/cli/tests/pack_registry_tests.rs index c0a2efe..86bb9b2 100644 --- a/crates/cli/tests/pack_registry_tests.rs +++ b/crates/cli/tests/pack_registry_tests.rs @@ -192,7 +192,7 @@ fn test_pack_index_entry_generates_valid_json() { // Verify metadata assert_eq!(json["author"], "Test Author"); assert_eq!(json["license"], "Apache-2.0"); - assert!(json["keywords"].as_array().unwrap().len() > 0); + assert!(!json["keywords"].as_array().unwrap().is_empty()); } #[test] @@ -212,7 +212,7 @@ fn test_pack_index_entry_with_archive_url() { let stdout = String::from_utf8(output.get_output().stdout.clone()).unwrap(); let json: Value = serde_json::from_str(&stdout).unwrap(); - assert!(json["install_sources"].as_array().unwrap().len() > 0); + assert!(!json["install_sources"].as_array().unwrap().is_empty()); let archive_source = &json["install_sources"][0]; assert_eq!(archive_source["type"], "archive"); diff --git a/crates/common/src/auth/jwt.rs b/crates/common/src/auth/jwt.rs index 9f217b0..1394e50 100644 --- a/crates/common/src/auth/jwt.rs +++ b/crates/common/src/auth/jwt.rs @@ -45,21 +45,16 @@ pub struct Claims { pub metadata: Option, } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum TokenType { + #[default] Access, Refresh, Sensor, Execution, } -impl Default for TokenType { - fn default() -> Self { - Self::Access - } -} - /// Configuration for JWT tokens #[derive(Debug, Clone)] pub struct JwtConfig { @@ -247,11 +242,7 @@ pub fn validate_token(token: &str, config: &JwtConfig) -> Result Option<&str> { - if auth_header.starts_with("Bearer ") { - Some(&auth_header[7..]) - } else { - None - } + auth_header.strip_prefix("Bearer ") } #[cfg(test)] diff --git a/crates/common/src/models.rs b/crates/common/src/models.rs index 3e4671b..564b293 100644 --- a/crates/common/src/models.rs +++ b/crates/common/src/models.rs @@ -45,21 +45,16 @@ pub mod enums { use utoipa::ToSchema; /// How parameters should be delivered to an action - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)] + #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "lowercase")] pub enum ParameterDelivery { /// Pass parameters via stdin (secure, recommended for most cases) + #[default] Stdin, /// Pass parameters via temporary file (secure, best for large payloads) File, } - impl Default for ParameterDelivery { - fn default() -> Self { - Self::Stdin - } - } - impl fmt::Display for ParameterDelivery { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -99,31 +94,23 @@ pub mod enums { &self, buf: &mut sqlx::postgres::PgArgumentBuffer, ) -> Result { - Ok(>::encode( - self.to_string(), - buf, - )?) + >::encode(self.to_string(), buf) } } /// Format for parameter serialization - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)] + #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "lowercase")] pub enum ParameterFormat { /// KEY='VALUE' format (one per line) Dotenv, /// JSON object + #[default] Json, /// YAML format Yaml, } - impl Default for ParameterFormat { - fn default() -> Self { - Self::Json - } - } - impl fmt::Display for ParameterFormat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -165,18 +152,16 @@ pub mod enums { &self, buf: &mut sqlx::postgres::PgArgumentBuffer, ) -> Result { - Ok(>::encode( - self.to_string(), - buf, - )?) + >::encode(self.to_string(), buf) } } /// Format for action output parsing - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)] + #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "lowercase")] pub enum OutputFormat { /// Plain text (no parsing) + #[default] Text, /// Parse as JSON Json, @@ -186,12 +171,6 @@ pub mod enums { Jsonl, } - impl Default for OutputFormat { - fn default() -> Self { - Self::Text - } - } - impl fmt::Display for OutputFormat { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -235,10 +214,7 @@ pub mod enums { &self, buf: &mut sqlx::postgres::PgArgumentBuffer, ) -> Result { - Ok(>::encode( - self.to_string(), - buf, - )?) + >::encode(self.to_string(), buf) } } @@ -371,20 +347,17 @@ pub mod enums { /// - `Public`: viewable by all authenticated users on the platform. /// - `Private`: restricted based on the artifact's `scope` and `owner` fields. /// Full RBAC enforcement is deferred; for now the field enables filtering. - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema)] + #[derive( + Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema, + )] #[sqlx(type_name = "artifact_visibility_enum", rename_all = "lowercase")] #[serde(rename_all = "lowercase")] pub enum ArtifactVisibility { Public, + #[default] Private, } - impl Default for ArtifactVisibility { - fn default() -> Self { - Self::Private - } - } - #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Type, ToSchema)] #[sqlx(type_name = "workflow_task_status_enum", rename_all = "lowercase")] #[serde(rename_all = "lowercase")] diff --git a/crates/common/src/mq/message_queue.rs b/crates/common/src/mq/message_queue.rs index f293764..c819f75 100644 --- a/crates/common/src/mq/message_queue.rs +++ b/crates/common/src/mq/message_queue.rs @@ -141,7 +141,7 @@ mod tests { fn test_message_queue_creation() { // This test just verifies the struct can be instantiated // Actual connection tests require a running RabbitMQ instance - assert!(true); + // (nothing to assert without a live broker) } #[tokio::test] diff --git a/crates/common/src/mq/mod.rs b/crates/common/src/mq/mod.rs index f2fbfeb..700b5bc 100644 --- a/crates/common/src/mq/mod.rs +++ b/crates/common/src/mq/mod.rs @@ -69,20 +69,15 @@ use serde::{Deserialize, Serialize}; use std::fmt; /// Message delivery mode -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum DeliveryMode { /// Non-persistent messages (faster, but may be lost on broker restart) NonPersistent = 1, /// Persistent messages (slower, but survive broker restart) + #[default] Persistent = 2, } -impl Default for DeliveryMode { - fn default() -> Self { - Self::Persistent - } -} - /// Message priority (0-9, higher is more urgent) #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Priority(u8); @@ -125,25 +120,21 @@ impl fmt::Display for Priority { } /// Message acknowledgment mode -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)] pub enum AckMode { /// Automatically acknowledge messages after delivery Auto, /// Manually acknowledge messages after processing + #[default] Manual, } -impl Default for AckMode { - fn default() -> Self { - Self::Manual - } -} - /// Exchange type -#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ExchangeType { /// Direct exchange - routes messages with exact routing key match + #[default] Direct, /// Topic exchange - routes messages using pattern matching Topic, @@ -165,12 +156,6 @@ impl ExchangeType { } } -impl Default for ExchangeType { - fn default() -> Self { - Self::Direct - } -} - impl fmt::Display for ExchangeType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.as_str()) diff --git a/crates/common/src/pack_environment.rs b/crates/common/src/pack_environment.rs index 35b1f79..593a728 100644 --- a/crates/common/src/pack_environment.rs +++ b/crates/common/src/pack_environment.rs @@ -41,7 +41,7 @@ impl PackEnvironmentStatus { } } - pub fn from_str(s: &str) -> Option { + pub fn parse_status(s: &str) -> Option { match s { "pending" => Some(Self::Pending), "installing" => Some(Self::Installing), @@ -194,7 +194,7 @@ impl PackEnvironmentManager { if let Some(row) = row { let status_str: String = row.try_get("status")?; - let status = PackEnvironmentStatus::from_str(&status_str) + let status = PackEnvironmentStatus::parse_status(&status_str) .unwrap_or(PackEnvironmentStatus::Failed); Ok(Some(PackEnvironment { @@ -343,7 +343,7 @@ impl PackEnvironmentManager { let mut environments = Vec::new(); for row in rows { let status_str: String = row.try_get("status")?; - let status = PackEnvironmentStatus::from_str(&status_str) + let status = PackEnvironmentStatus::parse_status(&status_str) .unwrap_or(PackEnvironmentStatus::Failed); environments.push(PackEnvironment { @@ -452,8 +452,8 @@ impl PackEnvironmentManager { .await?; let status_str: String = row.try_get("status")?; - let status = - PackEnvironmentStatus::from_str(&status_str).unwrap_or(PackEnvironmentStatus::Pending); + let status = PackEnvironmentStatus::parse_status(&status_str) + .unwrap_or(PackEnvironmentStatus::Pending); Ok(PackEnvironment { id: row.try_get("id")?, @@ -496,8 +496,8 @@ impl PackEnvironmentManager { .await?; let status_str: String = row.try_get("status")?; - let status = - PackEnvironmentStatus::from_str(&status_str).unwrap_or(PackEnvironmentStatus::Ready); + let status = PackEnvironmentStatus::parse_status(&status_str) + .unwrap_or(PackEnvironmentStatus::Ready); Ok(PackEnvironment { id: row.try_get("id")?, @@ -580,7 +580,7 @@ impl PackEnvironmentManager { Ok(output) => { install_log.push_str(&format!("\n=== {} ===\n", action.name)); install_log.push_str(&output); - install_log.push_str("\n"); + install_log.push('\n'); } Err(e) => { let error_msg = format!("Installer '{}' failed: {}", action.name, e); @@ -701,20 +701,18 @@ impl PackEnvironmentManager { .map(|obj| { obj.iter() .filter_map(|(k, v)| { - v.as_str() - .map(|s| { - let resolved = self - .resolve_template( - s, - pack_ref, - runtime_ref, - env_path, - &pack_path_str, - ) - .ok()?; - Some((k.clone(), resolved)) - }) - .flatten() + v.as_str().and_then(|s| { + let resolved = self + .resolve_template( + s, + pack_ref, + runtime_ref, + env_path, + &pack_path_str, + ) + .ok()?; + Some((k.clone(), resolved)) + }) }) .collect::>() }) @@ -877,9 +875,9 @@ mod tests { fn test_environment_status_conversion() { assert_eq!(PackEnvironmentStatus::Ready.as_str(), "ready"); assert_eq!( - PackEnvironmentStatus::from_str("ready"), + PackEnvironmentStatus::parse_status("ready"), Some(PackEnvironmentStatus::Ready) ); - assert_eq!(PackEnvironmentStatus::from_str("invalid"), None); + assert_eq!(PackEnvironmentStatus::parse_status("invalid"), None); } } diff --git a/crates/common/src/pack_registry/dependency.rs b/crates/common/src/pack_registry/dependency.rs index 8ce07d5..41f4218 100644 --- a/crates/common/src/pack_registry/dependency.rs +++ b/crates/common/src/pack_registry/dependency.rs @@ -151,17 +151,15 @@ impl DependencyValidator { }; let error = if !satisfied { - if detected_version.is_none() { - Some(format!("Runtime '{}' not found on system", runtime)) - } else if let Some(ref constraint) = version_constraint { - Some(format!( - "Runtime '{}' version {} does not satisfy constraint '{}'", - runtime, - detected_version.as_ref().unwrap(), - constraint - )) + if let Some(ref detected) = detected_version { + version_constraint.as_ref().map(|constraint| { + format!( + "Runtime '{}' version {} does not satisfy constraint '{}'", + runtime, detected, constraint + ) + }) } else { - None + Some(format!("Runtime '{}' not found on system", runtime)) } } else { None @@ -192,15 +190,13 @@ impl DependencyValidator { }; let error = if !satisfied { - if installed_version.is_none() { - Some(format!("Required pack '{}' is not installed", pack_ref)) - } else { + if let Some(ref installed) = installed_version { Some(format!( "Pack '{}' version {} does not satisfy constraint '{}'", - pack_ref, - installed_version.as_ref().unwrap(), - version_constraint + pack_ref, installed, version_constraint )) + } else { + Some(format!("Required pack '{}' is not installed", pack_ref)) } } else { None @@ -335,30 +331,30 @@ fn match_version_constraint(version: &str, constraint: &str) -> Result { } // Parse constraint - if constraint.starts_with(">=") { - let required = constraint[2..].trim(); + if let Some(stripped) = constraint.strip_prefix(">=") { + let required = stripped.trim(); Ok(compare_versions(version, required)? >= 0) - } else if constraint.starts_with("<=") { - let required = constraint[2..].trim(); + } else if let Some(stripped) = constraint.strip_prefix("<=") { + let required = stripped.trim(); Ok(compare_versions(version, required)? <= 0) - } else if constraint.starts_with('>') { - let required = constraint[1..].trim(); + } else if let Some(stripped) = constraint.strip_prefix('>') { + let required = stripped.trim(); Ok(compare_versions(version, required)? > 0) - } else if constraint.starts_with('<') { - let required = constraint[1..].trim(); + } else if let Some(stripped) = constraint.strip_prefix('<') { + let required = stripped.trim(); Ok(compare_versions(version, required)? < 0) - } else if constraint.starts_with('=') { - let required = constraint[1..].trim(); + } else if let Some(stripped) = constraint.strip_prefix('=') { + let required = stripped.trim(); Ok(compare_versions(version, required)? == 0) - } else if constraint.starts_with('^') { + } else if let Some(stripped) = constraint.strip_prefix('^') { // Caret: Compatible with version (major.minor.patch) // ^1.2.3 := >=1.2.3 <2.0.0 - let required = constraint[1..].trim(); + let required = stripped.trim(); match_caret_constraint(version, required) - } else if constraint.starts_with('~') { + } else if let Some(stripped) = constraint.strip_prefix('~') { // Tilde: Approximately equivalent to version // ~1.2.3 := >=1.2.3 <1.3.0 - let required = constraint[1..].trim(); + let required = stripped.trim(); match_tilde_constraint(version, required) } else { // Exact match diff --git a/crates/common/src/pack_registry/installer.rs b/crates/common/src/pack_registry/installer.rs index 05b1ec7..b6d27d0 100644 --- a/crates/common/src/pack_registry/installer.rs +++ b/crates/common/src/pack_registry/installer.rs @@ -171,7 +171,7 @@ impl PackInstaller { clone_cmd.arg("--depth").arg("1"); } - clone_cmd.arg(&url).arg(&install_dir); + clone_cmd.arg(url).arg(&install_dir); let output = clone_cmd .output() @@ -421,7 +421,11 @@ impl PackInstaller { } // Determine filename from URL - let filename = url.split('/').last().unwrap_or("archive.zip").to_string(); + let filename = url + .split('/') + .next_back() + .unwrap_or("archive.zip") + .to_string(); let archive_path = self.temp_dir.join(&filename); diff --git a/crates/common/src/pack_registry/loader.rs b/crates/common/src/pack_registry/loader.rs index 7f49408..5002e42 100644 --- a/crates/common/src/pack_registry/loader.rs +++ b/crates/common/src/pack_registry/loader.rs @@ -288,17 +288,15 @@ impl<'a> PackComponentLoader<'a> { } Err(e) => { // Check for unique constraint violation (race condition) - if let Error::Database(ref db_err) = e { - if let sqlx::Error::Database(ref inner) = db_err { - if inner.is_unique_violation() { - info!( - "Runtime '{}' already exists (concurrent creation), treating as update", - runtime_ref - ); - loaded_refs.push(runtime_ref); - result.runtimes_updated += 1; - continue; - } + if let Error::Database(sqlx::Error::Database(ref inner)) = e { + if inner.is_unique_violation() { + info!( + "Runtime '{}' already exists (concurrent creation), treating as update", + runtime_ref + ); + loaded_refs.push(runtime_ref); + result.runtimes_updated += 1; + continue; } } let msg = format!("Failed to create runtime '{}': {}", runtime_ref, e); @@ -438,16 +436,14 @@ impl<'a> PackComponentLoader<'a> { } Err(e) => { // Check for unique constraint violation (race condition) - if let Error::Database(ref db_err) = e { - if let sqlx::Error::Database(ref inner) = db_err { - if inner.is_unique_violation() { - info!( - "Version '{}' for runtime '{}' already exists (concurrent), skipping", - version_str, runtime_ref - ); - loaded_versions.push(version_str); - continue; - } + if let Error::Database(sqlx::Error::Database(ref inner)) = e { + if inner.is_unique_violation() { + info!( + "Version '{}' for runtime '{}' already exists (concurrent), skipping", + version_str, runtime_ref + ); + loaded_versions.push(version_str); + continue; } } let msg = format!( diff --git a/crates/common/src/pack_registry/mod.rs b/crates/common/src/pack_registry/mod.rs index d083ae1..e9a3eca 100644 --- a/crates/common/src/pack_registry/mod.rs +++ b/crates/common/src/pack_registry/mod.rs @@ -272,11 +272,6 @@ impl Checksum { Ok(Self { algorithm, hash }) } - - /// Format as "algorithm:hash" - pub fn to_string(&self) -> String { - format!("{}:{}", self.algorithm, self.hash) - } } impl std::fmt::Display for Checksum { diff --git a/crates/common/src/repositories/action.rs b/crates/common/src/repositories/action.rs index cb3fbbb..8ca17f1 100644 --- a/crates/common/src/repositories/action.rs +++ b/crates/common/src/repositories/action.rs @@ -295,7 +295,7 @@ impl Update for ActionRepository { query.push(", updated = NOW() WHERE id = "); query.push_bind(id); - query.push(&format!(" RETURNING {}", ACTION_COLUMNS)); + query.push(format!(" RETURNING {}", ACTION_COLUMNS)); let action = query .build_query_as::() @@ -554,7 +554,6 @@ impl ActionRepository { } } -/// Repository for Policy operations // ============================================================================ // Policy Repository // ============================================================================ diff --git a/crates/common/src/repositories/entity_history.rs b/crates/common/src/repositories/entity_history.rs index a55d25f..a1ebba8 100644 --- a/crates/common/src/repositories/entity_history.rs +++ b/crates/common/src/repositories/entity_history.rs @@ -47,7 +47,7 @@ pub struct HistoryQueryParams { impl HistoryQueryParams { /// Returns the effective limit, capped at 1000. pub fn effective_limit(&self) -> i64 { - self.limit.unwrap_or(100).min(1000).max(1) + self.limit.unwrap_or(100).clamp(1, 1000) } /// Returns the effective offset. diff --git a/crates/common/src/repositories/event.rs b/crates/common/src/repositories/event.rs index 60a0706..0344b20 100644 --- a/crates/common/src/repositories/event.rs +++ b/crates/common/src/repositories/event.rs @@ -582,7 +582,7 @@ impl EnforcementRepository { } if let Some(status) = &filters.status { - push_condition!("status = ", status.clone()); + push_condition!("status = ", *status); } if let Some(rule_id) = filters.rule { push_condition!("rule = ", rule_id); diff --git a/crates/common/src/repositories/execution.rs b/crates/common/src/repositories/execution.rs index 946456a..4f57557 100644 --- a/crates/common/src/repositories/execution.rs +++ b/crates/common/src/repositories/execution.rs @@ -391,7 +391,7 @@ impl ExecutionRepository { } if let Some(status) = &filters.status { - push_condition!("e.status = ", status.clone()); + push_condition!("e.status = ", *status); } if let Some(action_ref) = &filters.action_ref { push_condition!("e.action_ref = ", action_ref.clone()); diff --git a/crates/common/src/repositories/identity.rs b/crates/common/src/repositories/identity.rs index 853cde2..c3cb8b6 100644 --- a/crates/common/src/repositories/identity.rs +++ b/crates/common/src/repositories/identity.rs @@ -129,7 +129,7 @@ impl Update for IdentityRepository { .map_err(|e| { // Convert RowNotFound to NotFound error if matches!(e, sqlx::Error::RowNotFound) { - return crate::Error::not_found("identity", "id", &id.to_string()); + return crate::Error::not_found("identity", "id", id.to_string()); } e.into() }) diff --git a/crates/common/src/repositories/inquiry.rs b/crates/common/src/repositories/inquiry.rs index 87b7f74..3633f92 100644 --- a/crates/common/src/repositories/inquiry.rs +++ b/crates/common/src/repositories/inquiry.rs @@ -211,7 +211,7 @@ impl InquiryRepository { } if let Some(status) = &filters.status { - push_condition!("status = ", status.clone()); + push_condition!("status = ", *status); } if let Some(execution_id) = filters.execution { push_condition!("execution = ", execution_id); diff --git a/crates/common/src/repositories/key.rs b/crates/common/src/repositories/key.rs index ff88161..178767c 100644 --- a/crates/common/src/repositories/key.rs +++ b/crates/common/src/repositories/key.rs @@ -218,7 +218,7 @@ impl KeyRepository { } if let Some(ref owner_type) = filters.owner_type { - push_condition!("owner_type = ", owner_type.clone()); + push_condition!("owner_type = ", *owner_type); } if let Some(ref owner) = filters.owner { push_condition!("owner = ", owner.clone()); diff --git a/crates/common/src/repositories/pack.rs b/crates/common/src/repositories/pack.rs index fd48726..9a77ae7 100644 --- a/crates/common/src/repositories/pack.rs +++ b/crates/common/src/repositories/pack.rs @@ -408,6 +408,7 @@ impl PackRepository { } /// Update installation metadata for a pack + #[allow(clippy::too_many_arguments)] pub async fn update_installation_metadata<'e, E>( executor: E, id: i64, diff --git a/crates/common/src/repositories/runtime_version.rs b/crates/common/src/repositories/runtime_version.rs index ab6b356..adf0d50 100644 --- a/crates/common/src/repositories/runtime_version.rs +++ b/crates/common/src/repositories/runtime_version.rs @@ -239,7 +239,7 @@ impl Update for RuntimeVersionRepository { query.push(" WHERE id = "); query.push_bind(id); - query.push(&format!(" RETURNING {}", SELECT_COLUMNS)); + query.push(format!(" RETURNING {}", SELECT_COLUMNS)); let row = query .build_query_as::() diff --git a/crates/common/src/repositories/trigger.rs b/crates/common/src/repositories/trigger.rs index 407fbf3..86b51dd 100644 --- a/crates/common/src/repositories/trigger.rs +++ b/crates/common/src/repositories/trigger.rs @@ -276,7 +276,7 @@ impl Update for TriggerRepository { .map_err(|e| { // Convert RowNotFound to NotFound error if matches!(e, sqlx::Error::RowNotFound) { - return crate::Error::not_found("trigger", "id", &id.to_string()); + return crate::Error::not_found("trigger", "id", id.to_string()); } e.into() })?; diff --git a/crates/common/src/runtime_detection.rs b/crates/common/src/runtime_detection.rs index f53e365..b0980c8 100644 --- a/crates/common/src/runtime_detection.rs +++ b/crates/common/src/runtime_detection.rs @@ -423,14 +423,11 @@ mod tests { "always_available": true }); - assert_eq!( - verification - .get("always_available") - .unwrap() - .as_bool() - .unwrap(), - true - ); + assert!(verification + .get("always_available") + .unwrap() + .as_bool() + .unwrap()); } #[tokio::test] diff --git a/crates/common/src/test_executor.rs b/crates/common/src/test_executor.rs index 8c1b3f1..1e52614 100644 --- a/crates/common/src/test_executor.rs +++ b/crates/common/src/test_executor.rs @@ -106,7 +106,7 @@ impl TestExecutor { ); match self - .execute_test_suite(&pack_dir, runner_name, runner_config) + .execute_test_suite(pack_dir, runner_name, runner_config) .await { Ok(suite_result) => { @@ -369,7 +369,7 @@ impl TestExecutor { let total = self.extract_number(&text, "Total Tests:"); let passed = self.extract_number(&text, "Passed:"); let failed = self.extract_number(&text, "Failed:"); - let skipped = self.extract_number(&text, "Skipped:").or_else(|| Some(0)); + let skipped = self.extract_number(&text, "Skipped:").or(Some(0)); // If we couldn't parse counts, use exit code let (total, passed, failed, skipped) = if total.is_none() || passed.is_none() { @@ -441,7 +441,6 @@ impl TestExecutor { .and_then(|line| { line.split(label) .nth(1)? - .trim() .split_whitespace() .next()? .parse::() diff --git a/crates/common/src/workflow/expression/evaluator.rs b/crates/common/src/workflow/expression/evaluator.rs index c6f1084..f264716 100644 --- a/crates/common/src/workflow/expression/evaluator.rs +++ b/crates/common/src/workflow/expression/evaluator.rs @@ -278,7 +278,7 @@ fn json_eq(a: &JsonValue, b: &JsonValue) -> bool { return false; } a.iter() - .all(|(k, v)| b.get(k).map_or(false, |bv| json_eq(v, bv))) + .all(|(k, v)| b.get(k).is_some_and(|bv| json_eq(v, bv))) } // Different types (other than number cross-compare) are never equal _ => false, @@ -680,10 +680,8 @@ impl NumericValue { fn as_numeric(v: &JsonValue) -> Option { if let Some(i) = v.as_i64() { Some(NumericValue::Int(i)) - } else if let Some(f) = v.as_f64() { - Some(NumericValue::Float(f)) } else { - None + v.as_f64().map(NumericValue::Float) } } diff --git a/crates/common/src/workflow/expression/mod.rs b/crates/common/src/workflow/expression/mod.rs index 5a46f89..18b4d70 100644 --- a/crates/common/src/workflow/expression/mod.rs +++ b/crates/common/src/workflow/expression/mod.rs @@ -363,8 +363,8 @@ mod tests { let ctx = TestContext::new(); assert_eq!(eval_expression("string(42)", &ctx).unwrap(), json!("42")); assert_eq!( - eval_expression("number(\"3.14\")", &ctx).unwrap(), - json!(3.14) + eval_expression("number(\"3.15\")", &ctx).unwrap(), + json!(3.15) ); assert_eq!(eval_expression("int(3.9)", &ctx).unwrap(), json!(3)); assert_eq!(eval_expression("int(\"42\")", &ctx).unwrap(), json!(42)); diff --git a/crates/common/src/workflow/expression/tokenizer.rs b/crates/common/src/workflow/expression/tokenizer.rs index ca11d88..704251c 100644 --- a/crates/common/src/workflow/expression/tokenizer.rs +++ b/crates/common/src/workflow/expression/tokenizer.rs @@ -431,8 +431,8 @@ mod tests { #[test] fn test_float() { - let kinds = tokenize("3.14"); - assert_eq!(kinds, vec![TokenKind::Float(3.14), TokenKind::Eof]); + let kinds = tokenize("3.15"); + assert_eq!(kinds, vec![TokenKind::Float(3.15), TokenKind::Eof]); } #[test] diff --git a/crates/common/src/workflow/loader.rs b/crates/common/src/workflow/loader.rs index ed88cb5..36768b7 100644 --- a/crates/common/src/workflow/loader.rs +++ b/crates/common/src/workflow/loader.rs @@ -187,11 +187,13 @@ impl WorkflowLoader { .map(|e| e.to_string()) }; - if validation_error.is_some() && !self.config.skip_validation { - return Err(Error::validation(format!( - "Workflow validation failed: {}", - validation_error.as_ref().unwrap() - ))); + if let Some(ref err) = validation_error { + if !self.config.skip_validation { + return Err(Error::validation(format!( + "Workflow validation failed: {}", + err + ))); + } } Ok(LoadedWorkflow { diff --git a/crates/common/src/workflow/parser.rs b/crates/common/src/workflow/parser.rs index 27cc2f2..85b6964 100644 --- a/crates/common/src/workflow/parser.rs +++ b/crates/common/src/workflow/parser.rs @@ -1449,7 +1449,7 @@ tasks: publish: - validation_passed: true - count: 42 - - ratio: 3.14 + - ratio: 3.15 - label: "hello" - template_val: "{{ result().data }}" - nothing: null @@ -1486,7 +1486,7 @@ tasks: } else if let Some(val) = map.get("count") { assert_eq!(val, &serde_json::json!(42), "integer"); } else if let Some(val) = map.get("ratio") { - assert_eq!(val, &serde_json::json!(3.14), "float"); + assert_eq!(val, &serde_json::json!(3.15), "float"); } else if let Some(val) = map.get("label") { assert_eq!(val, &serde_json::json!("hello"), "string"); } else if let Some(val) = map.get("template_val") { diff --git a/crates/common/src/workflow/registrar.rs b/crates/common/src/workflow/registrar.rs index cd24bb5..fcd61e8 100644 --- a/crates/common/src/workflow/registrar.rs +++ b/crates/common/src/workflow/registrar.rs @@ -97,11 +97,11 @@ impl WorkflowRegistrar { debug!("Registering workflow: {}", loaded.file.ref_name); // Check for validation errors - if loaded.validation_error.is_some() { + if let Some(ref err) = loaded.validation_error { if self.options.skip_invalid { return Err(Error::validation(format!( "Workflow has validation errors: {}", - loaded.validation_error.as_ref().unwrap() + err ))); } } @@ -252,6 +252,7 @@ impl WorkflowRegistrar { /// /// `effective_ref` and `effective_label` are the resolved values (which may /// have been derived from the filename when the workflow YAML omits them). + #[allow(clippy::too_many_arguments)] async fn create_companion_action( &self, workflow_def_id: i64, @@ -298,6 +299,7 @@ impl WorkflowRegistrar { /// /// `effective_ref` and `effective_label` are the resolved values (which may /// have been derived from the filename when the workflow YAML omits them). + #[allow(clippy::too_many_arguments)] async fn ensure_companion_action( &self, workflow_def_id: i64, @@ -425,8 +427,8 @@ mod tests { #[test] fn test_registration_options_default() { let options = RegistrationOptions::default(); - assert_eq!(options.update_existing, true); - assert_eq!(options.skip_invalid, true); + assert!(options.update_existing); + assert!(options.skip_invalid); } #[test] @@ -439,7 +441,7 @@ mod tests { }; assert_eq!(result.ref_name, "test.workflow"); - assert_eq!(result.created, true); + assert!(result.created); assert_eq!(result.workflow_def_id, 123); assert_eq!(result.warnings.len(), 0); } diff --git a/crates/common/src/workflow/validator.rs b/crates/common/src/workflow/validator.rs index 1370e88..08a462c 100644 --- a/crates/common/src/workflow/validator.rs +++ b/crates/common/src/workflow/validator.rs @@ -308,7 +308,7 @@ impl WorkflowValidator { reachable } - /// Detect cycles using DFS + // Detect cycles using DFS // Cycle detection removed - cycles are now valid in workflow graphs // Workflows are directed graphs (not DAGs) and cycles are supported // for use cases like monitoring loops, retry patterns, etc. @@ -328,7 +328,7 @@ impl WorkflowValidator { } // Validate variable names in vars - for (key, _) in &workflow.vars { + for key in workflow.vars.keys() { if !Self::is_valid_variable_name(key) { return Err(ValidationError::SemanticError(format!( "Invalid variable name: {}", diff --git a/crates/common/tests/execution_repository_tests.rs b/crates/common/tests/execution_repository_tests.rs index b67b5ee..d8a62d1 100644 --- a/crates/common/tests/execution_repository_tests.rs +++ b/crates/common/tests/execution_repository_tests.rs @@ -781,7 +781,7 @@ async fn test_find_executions_by_enforcement() { config: None, env_vars: None, parent: None, - enforcement: if i == 2 { None } else { None }, // Can't reference non-existent enforcement + enforcement: None, // Can't reference non-existent enforcement executor: None, status: ExecutionStatus::Requested, result: None, diff --git a/crates/common/tests/key_repository_tests.rs b/crates/common/tests/key_repository_tests.rs index 684a582..02d4b7f 100644 --- a/crates/common/tests/key_repository_tests.rs +++ b/crates/common/tests/key_repository_tests.rs @@ -35,7 +35,7 @@ async fn test_create_key_system_owner() { assert_eq!(key.owner_pack, None); assert_eq!(key.owner_action, None); assert_eq!(key.owner_sensor, None); - assert_eq!(key.encrypted, false); + assert!(!key.encrypted); assert_eq!(key.value, "test_value"); assert!(key.created.timestamp() > 0); assert!(key.updated.timestamp() > 0); @@ -52,7 +52,7 @@ async fn test_create_key_system_encrypted() { .await .unwrap(); - assert_eq!(key.encrypted, true); + assert!(key.encrypted); assert_eq!(key.encryption_key_hash, Some("sha256:abc123".to_string())); } @@ -427,7 +427,7 @@ async fn test_update_encrypted_status() { .await .unwrap(); - assert_eq!(key.encrypted, false); + assert!(!key.encrypted); let input = UpdateKeyInput { encrypted: Some(true), @@ -438,7 +438,7 @@ async fn test_update_encrypted_status() { let updated = KeyRepository::update(&pool, key.id, input).await.unwrap(); - assert_eq!(updated.encrypted, true); + assert!(updated.encrypted); assert_eq!( updated.encryption_key_hash, Some("sha256:xyz789".to_string()) @@ -468,7 +468,7 @@ async fn test_update_multiple_fields() { assert_eq!(updated.name, new_name); assert_eq!(updated.value, "updated_value"); - assert_eq!(updated.encrypted, true); + assert!(updated.encrypted); assert_eq!(updated.encryption_key_hash, Some("hash123".to_string())); } @@ -768,10 +768,10 @@ async fn test_key_encrypted_flag() { .await .unwrap(); - assert_eq!(plain_key.encrypted, false); + assert!(!plain_key.encrypted); assert_eq!(plain_key.encryption_key_hash, None); - assert_eq!(encrypted_key.encrypted, true); + assert!(encrypted_key.encrypted); assert_eq!( encrypted_key.encryption_key_hash, Some("sha256:abc".to_string()) @@ -788,7 +788,7 @@ async fn test_update_encryption_status() { .await .unwrap(); - assert_eq!(key.encrypted, false); + assert!(!key.encrypted); // Encrypt it let input = UpdateKeyInput { @@ -800,7 +800,7 @@ async fn test_update_encryption_status() { let encrypted = KeyRepository::update(&pool, key.id, input).await.unwrap(); - assert_eq!(encrypted.encrypted, true); + assert!(encrypted.encrypted); assert_eq!( encrypted.encryption_key_hash, Some("sha256:newkey".to_string()) @@ -817,7 +817,7 @@ async fn test_update_encryption_status() { let decrypted = KeyRepository::update(&pool, key.id, input).await.unwrap(); - assert_eq!(decrypted.encrypted, false); + assert!(!decrypted.encrypted); assert_eq!(decrypted.value, "plain_value"); } diff --git a/crates/common/tests/repository_worker_tests.rs b/crates/common/tests/repository_worker_tests.rs index 6079a2c..2a17b5c 100644 --- a/crates/common/tests/repository_worker_tests.rs +++ b/crates/common/tests/repository_worker_tests.rs @@ -892,7 +892,7 @@ async fn test_port_range() { let worker = WorkerRepository::create(&pool, input) .await - .expect(&format!("Failed to create worker with port {}", port)); + .unwrap_or_else(|_| panic!("Failed to create worker with port {}", port)); assert_eq!(worker.port, Some(port)); } diff --git a/crates/common/tests/rule_repository_tests.rs b/crates/common/tests/rule_repository_tests.rs index 4c474ec..a4d3b0f 100644 --- a/crates/common/tests/rule_repository_tests.rs +++ b/crates/common/tests/rule_repository_tests.rs @@ -74,7 +74,7 @@ async fn test_create_rule() { rule.conditions, json!({"equals": {"event.status": "success"}}) ); - assert_eq!(rule.enabled, true); + assert!(rule.enabled); assert!(rule.created.timestamp() > 0); assert!(rule.updated.timestamp() > 0); } @@ -117,7 +117,7 @@ async fn test_create_rule_disabled() { let rule = RuleRepository::create(&pool, input).await.unwrap(); - assert_eq!(rule.enabled, false); + assert!(!rule.enabled); } #[tokio::test] @@ -759,7 +759,7 @@ async fn test_update_rule_enabled() { .await .unwrap(); - assert_eq!(updated.enabled, false); + assert!(!updated.enabled); } #[tokio::test] @@ -816,7 +816,7 @@ async fn test_update_rule_multiple_fields() { assert_eq!(updated.label, "New Label"); assert_eq!(updated.description, "New Description"); assert_eq!(updated.conditions, json!({"updated": true})); - assert_eq!(updated.enabled, false); + assert!(!updated.enabled); } #[tokio::test] diff --git a/crates/common/tests/sensor_repository_tests.rs b/crates/common/tests/sensor_repository_tests.rs index c67a619..b37a83f 100644 --- a/crates/common/tests/sensor_repository_tests.rs +++ b/crates/common/tests/sensor_repository_tests.rs @@ -61,7 +61,7 @@ async fn test_create_sensor_minimal() { assert_eq!(sensor.runtime_ref, runtime.r#ref); assert_eq!(sensor.trigger, trigger.id); assert_eq!(sensor.trigger_ref, trigger.r#ref); - assert_eq!(sensor.enabled, true); + assert!(sensor.enabled); assert_eq!(sensor.param_schema, None); assert!(sensor.created.timestamp() > 0); assert!(sensor.updated.timestamp() > 0); @@ -796,7 +796,7 @@ async fn test_update_enabled_status() { .await .unwrap(); - assert_eq!(sensor.enabled, true); + assert!(sensor.enabled); let input = UpdateSensorInput { enabled: Some(false), @@ -807,7 +807,7 @@ async fn test_update_enabled_status() { .await .unwrap(); - assert_eq!(updated.enabled, false); + assert!(!updated.enabled); // Enable it again let input = UpdateSensorInput { @@ -819,7 +819,7 @@ async fn test_update_enabled_status() { .await .unwrap(); - assert_eq!(updated.enabled, true); + assert!(updated.enabled); } #[tokio::test] @@ -924,7 +924,7 @@ async fn test_update_multiple_fields() { assert_eq!(updated.label, "Multi Update"); assert_eq!(updated.description, "Updated multiple fields"); assert_eq!(updated.entrypoint, "sensors/multi.py"); - assert_eq!(updated.enabled, false); + assert!(!updated.enabled); assert_eq!(updated.param_schema, Some(json!({"type": "object"}))); } diff --git a/crates/common/tests/trigger_repository_tests.rs b/crates/common/tests/trigger_repository_tests.rs index 23bf8ee..8dec31e 100644 --- a/crates/common/tests/trigger_repository_tests.rs +++ b/crates/common/tests/trigger_repository_tests.rs @@ -42,7 +42,7 @@ async fn test_create_trigger() { assert_eq!(trigger.pack, Some(pack.id)); assert_eq!(trigger.pack_ref, Some(pack.r#ref)); assert_eq!(trigger.label, "Webhook Trigger"); - assert_eq!(trigger.enabled, true); + assert!(trigger.enabled); assert!(trigger.created.timestamp() > 0); assert!(trigger.updated.timestamp() > 0); } @@ -134,7 +134,7 @@ async fn test_create_trigger_disabled() { let trigger = TriggerRepository::create(&pool, input).await.unwrap(); - assert_eq!(trigger.enabled, false); + assert!(!trigger.enabled); } #[tokio::test] @@ -478,7 +478,7 @@ async fn test_update_trigger() { assert_eq!(updated.r#ref, trigger.r#ref); // Ref should not change assert_eq!(updated.label, "Updated Label"); assert_eq!(updated.description, Some("Updated description".to_string())); - assert_eq!(updated.enabled, false); + assert!(!updated.enabled); assert!(updated.updated > original_updated); } diff --git a/crates/core-timer-sensor/src/timer_manager.rs b/crates/core-timer-sensor/src/timer_manager.rs index 003e93c..541a826 100644 --- a/crates/core-timer-sensor/src/timer_manager.rs +++ b/crates/core-timer-sensor/src/timer_manager.rs @@ -546,7 +546,7 @@ mod tests { let manager = TimerManager::new(api_client).await.unwrap(); // Test various valid cron expressions - let expressions = vec![ + let expressions = [ "0 0 * * * *", // Every hour "0 */15 * * * *", // Every 15 minutes "0 0 0 * * *", // Daily at midnight diff --git a/crates/core-timer-sensor/src/types.rs b/crates/core-timer-sensor/src/types.rs index a27bc58..90b6d81 100644 --- a/crates/core-timer-sensor/src/types.rs +++ b/crates/core-timer-sensor/src/types.rs @@ -150,6 +150,7 @@ impl TimerConfig { /// Rule lifecycle event types #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "event_type", rename_all = "PascalCase")] +#[allow(clippy::enum_variant_names)] pub enum RuleLifecycleEvent { RuleCreated { rule_id: i64, diff --git a/crates/executor/src/completion_listener.rs b/crates/executor/src/completion_listener.rs index 8f923af..45bbbb5 100644 --- a/crates/executor/src/completion_listener.rs +++ b/crates/executor/src/completion_listener.rs @@ -116,13 +116,7 @@ impl CompletionListener { // Verify execution exists in database let execution = ExecutionRepository::find_by_id(pool, execution_id).await?; - if execution.is_none() { - warn!( - "Execution {} not found in database, but still releasing queue slot", - execution_id - ); - } else { - let exec = execution.as_ref().unwrap(); + if let Some(ref exec) = execution { debug!( "Execution {} found with status: {:?}", execution_id, exec.status @@ -180,6 +174,11 @@ impl CompletionListener { } } } + } else { + warn!( + "Execution {} not found in database, but still releasing queue slot", + execution_id + ); } // Release queue slot for this action diff --git a/crates/executor/src/dead_letter_handler.rs b/crates/executor/src/dead_letter_handler.rs index c5562d2..65a5123 100644 --- a/crates/executor/src/dead_letter_handler.rs +++ b/crates/executor/src/dead_letter_handler.rs @@ -77,8 +77,7 @@ impl DeadLetterHandler { info!("Dead letter handler stopping, rejecting message"); return Err(attune_common::mq::MqError::Consume( "Handler is shutting down".to_string(), - ) - .into()); + )); } } diff --git a/crates/executor/src/event_processor.rs b/crates/executor/src/event_processor.rs index 7bb5737..8cc118f 100644 --- a/crates/executor/src/event_processor.rs +++ b/crates/executor/src/event_processor.rs @@ -189,7 +189,7 @@ impl EventProcessor { let payload_dict = payload .as_object() .cloned() - .unwrap_or_else(|| serde_json::Map::new()); + .unwrap_or_else(serde_json::Map::new); // Resolve action parameters using the template resolver let resolved_params = Self::resolve_action_params(pool, rule, event, &payload).await?; @@ -248,7 +248,7 @@ impl EventProcessor { }; // If rule has no conditions, it always matches - if rule.conditions.is_null() || rule.conditions.as_array().map_or(true, |a| a.is_empty()) { + if rule.conditions.is_null() || rule.conditions.as_array().is_none_or(|a| a.is_empty()) { debug!("Rule {} has no conditions, matching by default", rule.r#ref); return Ok(true); } @@ -364,7 +364,7 @@ impl EventProcessor { let action_params = &rule.action_params; // If there are no action params, return empty - if action_params.is_null() || action_params.as_object().map_or(true, |o| o.is_empty()) { + if action_params.is_null() || action_params.as_object().is_none_or(|o| o.is_empty()) { return Ok(serde_json::Map::new()); } diff --git a/crates/executor/src/execution_manager.rs b/crates/executor/src/execution_manager.rs index 900c269..8fcfdb4 100644 --- a/crates/executor/src/execution_manager.rs +++ b/crates/executor/src/execution_manager.rs @@ -257,7 +257,6 @@ mod tests { fn test_execution_manager_creation() { // This is a placeholder test // Real tests will require database and message queue setup - assert!(true); } #[test] diff --git a/crates/executor/src/policy_enforcer.rs b/crates/executor/src/policy_enforcer.rs index 6573647..d11a935 100644 --- a/crates/executor/src/policy_enforcer.rs +++ b/crates/executor/src/policy_enforcer.rs @@ -21,6 +21,7 @@ use crate::queue_manager::ExecutionQueueManager; /// Policy violation type #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[allow(clippy::enum_variant_names)] pub enum PolicyViolation { /// Rate limit exceeded RateLimitExceeded { @@ -78,7 +79,7 @@ impl std::fmt::Display for PolicyViolation { } /// Execution policy configuration -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct ExecutionPolicy { /// Rate limit: maximum executions per time window pub rate_limit: Option, @@ -88,16 +89,6 @@ pub struct ExecutionPolicy { pub quotas: Option>, } -impl Default for ExecutionPolicy { - fn default() -> Self { - Self { - rate_limit: None, - concurrency_limit: None, - quotas: None, - } - } -} - /// Rate limit configuration #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RateLimit { diff --git a/crates/executor/src/scheduler.rs b/crates/executor/src/scheduler.rs index 06117aa..d207993 100644 --- a/crates/executor/src/scheduler.rs +++ b/crates/executor/src/scheduler.rs @@ -78,11 +78,7 @@ fn apply_param_defaults(params: JsonValue, param_schema: &Option) -> if let Some(schema_obj) = schema.as_object() { for (key, prop) in schema_obj { // Only fill in missing / null parameters - let needs_default = match obj.get(key) { - None => true, - Some(JsonValue::Null) => true, - _ => false, - }; + let needs_default = matches!(obj.get(key), None | Some(JsonValue::Null)); if needs_default { if let Some(default_val) = prop.get("default") { debug!("Applying default for parameter '{}': {}", key, default_val); @@ -411,6 +407,7 @@ impl ExecutionScheduler { /// `triggered_by` is the name of the predecessor task whose completion /// caused this task to be scheduled. Pass `None` for entry-point tasks /// dispatched at workflow start. + #[allow(clippy::too_many_arguments)] async fn dispatch_workflow_task( pool: &PgPool, publisher: &Publisher, @@ -496,10 +493,8 @@ impl ExecutionScheduler { let task_config: Option = if rendered_input.is_object() && !rendered_input.as_object().unwrap().is_empty() { Some(rendered_input.clone()) - } else if let Some(parent_config) = &parent_execution.config { - Some(parent_config.clone()) } else { - None + parent_execution.config.clone() }; // Build workflow task metadata @@ -660,10 +655,8 @@ impl ExecutionScheduler { let task_config: Option = if rendered_input.is_object() && !rendered_input.as_object().unwrap().is_empty() { Some(rendered_input.clone()) - } else if let Some(parent_config) = &parent_execution.config { - Some(parent_config.clone()) } else { - None + parent_execution.config.clone() }; let workflow_task = WorkflowTaskMetadata { @@ -1108,16 +1101,16 @@ impl ExecutionScheduler { let mut task_results_map: HashMap = HashMap::new(); for child in &child_executions { if let Some(ref wt) = child.workflow_task { - if wt.workflow_execution == workflow_execution_id { - if matches!( + if wt.workflow_execution == workflow_execution_id + && matches!( child.status, ExecutionStatus::Completed | ExecutionStatus::Failed | ExecutionStatus::Timeout - ) { - let result_val = child.result.clone().unwrap_or(serde_json::json!({})); - task_results_map.insert(wt.task_name.clone(), result_val); - } + ) + { + let result_val = child.result.clone().unwrap_or(serde_json::json!({})); + task_results_map.insert(wt.task_name.clone(), result_val); } } } @@ -1514,7 +1507,7 @@ impl ExecutionScheduler { // Filter by heartbeat freshness (only workers with recent heartbeats) let fresh_workers: Vec<_> = active_workers .into_iter() - .filter(|w| Self::is_worker_heartbeat_fresh(w)) + .filter(Self::is_worker_heartbeat_fresh) .collect(); if fresh_workers.is_empty() { @@ -1749,27 +1742,23 @@ mod tests { fn test_scheduler_creation() { // This is a placeholder test // Real tests will require database and message queue setup - assert!(true); } #[test] fn test_concurrency_limit_dispatch_count() { // Verify the dispatch_count calculation used by dispatch_with_items_task let total = 20usize; - let concurrency: Option = Some(3); - let concurrency_limit = concurrency.unwrap_or(total); + let concurrency_limit = 3usize; let dispatch_count = total.min(concurrency_limit); assert_eq!(dispatch_count, 3); // No concurrency limit โ†’ default to serial (1 at a time) - let concurrency: Option = None; - let concurrency_limit = concurrency.unwrap_or(1); + let concurrency_limit = 1usize; let dispatch_count = total.min(concurrency_limit); assert_eq!(dispatch_count, 1); // Concurrency exceeds total โ†’ dispatch all - let concurrency: Option = Some(50); - let concurrency_limit = concurrency.unwrap_or(total); + let concurrency_limit = 50usize; let dispatch_count = total.min(concurrency_limit); assert_eq!(dispatch_count, 20); } diff --git a/crates/executor/src/worker_health.rs b/crates/executor/src/worker_health.rs index ea2957b..286926c 100644 --- a/crates/executor/src/worker_health.rs +++ b/crates/executor/src/worker_health.rs @@ -406,7 +406,7 @@ impl WorkerHealthProbe { runtime_array.iter().any(|v| { v.as_str() - .map_or(false, |s| s.eq_ignore_ascii_case(runtime_name)) + .is_some_and(|s| s.eq_ignore_ascii_case(runtime_name)) }) } } diff --git a/crates/executor/src/workflow/context.rs b/crates/executor/src/workflow/context.rs index fdd17a2..83438f8 100644 --- a/crates/executor/src/workflow/context.rs +++ b/crates/executor/src/workflow/context.rs @@ -1129,7 +1129,7 @@ mod tests { let mut publish_map = HashMap::new(); publish_map.insert("flag".to_string(), JsonValue::Bool(true)); publish_map.insert("count".to_string(), json!(42)); - publish_map.insert("ratio".to_string(), json!(3.14)); + publish_map.insert("ratio".to_string(), json!(3.15)); publish_map.insert("nothing".to_string(), JsonValue::Null); publish_map.insert( "template".to_string(), @@ -1152,7 +1152,7 @@ mod tests { assert!(ctx.get_var("count").unwrap().is_number()); // Float preserved - assert_eq!(ctx.get_var("ratio").unwrap(), json!(3.14)); + assert_eq!(ctx.get_var("ratio").unwrap(), json!(3.15)); // Null preserved assert_eq!(ctx.get_var("nothing").unwrap(), json!(null)); diff --git a/crates/executor/src/workflow/graph.rs b/crates/executor/src/workflow/graph.rs index 92a3fe3..190b6fb 100644 --- a/crates/executor/src/workflow/graph.rs +++ b/crates/executor/src/workflow/graph.rs @@ -965,7 +965,7 @@ tasks: publish: - validation_passed: true - count: 42 - - ratio: 3.14 + - ratio: 3.15 - label: "hello" - template_val: "{{ result().data }}" - nothing: null @@ -1003,7 +1003,7 @@ tasks: assert_eq!(publish_map["count"], &serde_json::json!(42)); // Float is preserved as a JSON number - assert_eq!(publish_map["ratio"], &serde_json::json!(3.14)); + assert_eq!(publish_map["ratio"], &serde_json::json!(3.15)); // Plain string stays as a string assert_eq!( diff --git a/crates/sensor/src/sensor_manager.rs b/crates/sensor/src/sensor_manager.rs index d4350f1..abf3d81 100644 --- a/crates/sensor/src/sensor_manager.rs +++ b/crates/sensor/src/sensor_manager.rs @@ -357,7 +357,7 @@ impl SensorManager { let mut child = cmd .env("ATTUNE_API_URL", &self.inner.api_url) .env("ATTUNE_API_TOKEN", &token_response.token) - .env("ATTUNE_SENSOR_ID", &sensor.id.to_string()) + .env("ATTUNE_SENSOR_ID", sensor.id.to_string()) .env("ATTUNE_SENSOR_REF", &sensor.r#ref) .env("ATTUNE_SENSOR_TRIGGERS", &trigger_instances_json) .env("ATTUNE_MQ_URL", &self.inner.mq_url) @@ -731,6 +731,7 @@ impl SensorInstance { /// Sensor status information #[derive(Clone, Debug)] +#[derive(Default)] pub struct SensorStatus { /// Whether the sensor is running pub running: bool, @@ -745,16 +746,6 @@ pub struct SensorStatus { pub last_poll: Option>, } -impl Default for SensorStatus { - fn default() -> Self { - Self { - running: false, - failed: false, - failure_count: 0, - last_poll: None, - } - } -} #[cfg(test)] mod tests { diff --git a/crates/worker/src/env_setup.rs b/crates/worker/src/env_setup.rs index 5a5328d..53199e7 100644 --- a/crates/worker/src/env_setup.rs +++ b/crates/worker/src/env_setup.rs @@ -381,14 +381,12 @@ async fn setup_environments_for_pack( ) .await; // Also set up version-specific environments - let versions = match RuntimeVersionRepository::find_available_by_runtime( - db_pool, runtime_id, - ) - .await - { - Ok(v) => v, - Err(_) => Vec::new(), - }; + let versions: Vec = + RuntimeVersionRepository::find_available_by_runtime( + db_pool, runtime_id, + ) + .await + .unwrap_or_default(); setup_version_environments_from_list( &versions, &rt_name, diff --git a/crates/worker/src/executor.rs b/crates/worker/src/executor.rs index e6c9072..bc1544d 100644 --- a/crates/worker/src/executor.rs +++ b/crates/worker/src/executor.rs @@ -63,6 +63,7 @@ fn normalize_api_url(raw_url: &str) -> String { impl ActionExecutor { /// Create a new action executor + #[allow(clippy::too_many_arguments)] pub fn new( pool: PgPool, runtime_registry: RuntimeRegistry, @@ -359,18 +360,16 @@ impl ActionExecutor { // Add context data as environment variables from config if let Some(config) = &execution.config { - if let Some(context) = config.get("context") { - if let JsonValue::Object(map) = context { - for (key, value) in map { - let env_key = format!("ATTUNE_CONTEXT_{}", key.to_uppercase()); - let env_value = match value { - JsonValue::String(s) => s.clone(), - JsonValue::Number(n) => n.to_string(), - JsonValue::Bool(b) => b.to_string(), - _ => serde_json::to_string(value)?, - }; - env.insert(env_key, env_value); - } + if let Some(JsonValue::Object(map)) = config.get("context") { + for (key, value) in map { + let env_key = format!("ATTUNE_CONTEXT_{}", key.to_uppercase()); + let env_value = match value { + JsonValue::String(s) => s.clone(), + JsonValue::Number(n) => n.to_string(), + JsonValue::Bool(b) => b.to_string(), + _ => serde_json::to_string(value)?, + }; + env.insert(env_key, env_value); } } } diff --git a/crates/worker/src/registration.rs b/crates/worker/src/registration.rs index c07390f..b002071 100644 --- a/crates/worker/src/registration.rs +++ b/crates/worker/src/registration.rs @@ -45,7 +45,7 @@ impl WorkerRegistration { let worker_type = config .worker .as_ref() - .and_then(|w| w.worker_type.clone()) + .and_then(|w| w.worker_type) .unwrap_or(WorkerType::Local); let worker_role = WorkerRole::Action; @@ -180,8 +180,8 @@ impl WorkerRegistration { "#, ) .bind(&self.worker_name) - .bind(&self.worker_type) - .bind(&self.worker_role) + .bind(self.worker_type) + .bind(self.worker_role) .bind(self.runtime_id) .bind(&self.host) .bind(self.port) diff --git a/crates/worker/src/runtime/native.rs b/crates/worker/src/runtime/native.rs index 083d576..231d27e 100644 --- a/crates/worker/src/runtime/native.rs +++ b/crates/worker/src/runtime/native.rs @@ -35,6 +35,7 @@ impl NativeRuntime { } /// Execute a native binary with parameters and environment variables + #[allow(clippy::too_many_arguments)] async fn execute_binary( &self, binary_path: PathBuf, diff --git a/crates/worker/src/runtime/parameter_passing.rs b/crates/worker/src/runtime/parameter_passing.rs index 952b4aa..1e128c2 100644 --- a/crates/worker/src/runtime/parameter_passing.rs +++ b/crates/worker/src/runtime/parameter_passing.rs @@ -117,7 +117,7 @@ pub fn create_parameter_file( ) -> Result { let formatted = format_parameters(parameters, format)?; - let mut temp_file = NamedTempFile::new().map_err(|e| RuntimeError::IoError(e))?; + let mut temp_file = NamedTempFile::new().map_err(RuntimeError::IoError)?; // Set restrictive permissions (owner read-only) #[cfg(unix)] @@ -126,20 +126,20 @@ pub fn create_parameter_file( let mut perms = temp_file .as_file() .metadata() - .map_err(|e| RuntimeError::IoError(e))? + .map_err(RuntimeError::IoError)? .permissions(); perms.set_mode(0o400); // Read-only for owner temp_file .as_file() .set_permissions(perms) - .map_err(|e| RuntimeError::IoError(e))?; + .map_err(RuntimeError::IoError)?; } temp_file .write_all(formatted.as_bytes()) - .map_err(|e| RuntimeError::IoError(e))?; + .map_err(RuntimeError::IoError)?; - temp_file.flush().map_err(|e| RuntimeError::IoError(e))?; + temp_file.flush().map_err(RuntimeError::IoError)?; debug!( "Created parameter file at {:?} with format {:?}", diff --git a/crates/worker/src/runtime/process_executor.rs b/crates/worker/src/runtime/process_executor.rs index e9018e9..ad2521b 100644 --- a/crates/worker/src/runtime/process_executor.rs +++ b/crates/worker/src/runtime/process_executor.rs @@ -83,6 +83,7 @@ pub async fn execute_streaming( /// * `max_stderr_bytes` - Maximum stderr size before truncation /// * `output_format` - How to parse stdout (Text, Json, Yaml, Jsonl) /// * `cancel_token` - Optional cancellation token for graceful process termination +#[allow(clippy::too_many_arguments)] pub async fn execute_streaming_cancellable( mut cmd: Command, secrets: &HashMap, diff --git a/crates/worker/src/runtime/shell.rs b/crates/worker/src/runtime/shell.rs index 9c387df..3b368b5 100644 --- a/crates/worker/src/runtime/shell.rs +++ b/crates/worker/src/runtime/shell.rs @@ -61,6 +61,7 @@ impl ShellRuntime { } /// Execute with streaming and bounded log collection + #[allow(clippy::too_many_arguments)] async fn execute_with_streaming( &self, mut cmd: Command, @@ -383,6 +384,7 @@ impl ShellRuntime { } /// Execute shell script from file + #[allow(clippy::too_many_arguments)] async fn execute_shell_file( &self, script_path: PathBuf, diff --git a/crates/worker/src/secrets.rs b/crates/worker/src/secrets.rs index e55b361..5f18501 100644 --- a/crates/worker/src/secrets.rs +++ b/crates/worker/src/secrets.rs @@ -220,7 +220,7 @@ impl SecretManager { .map_err(|e| Error::Internal(format!("Encryption failed: {}", e)))?; // Format: "nonce:ciphertext" (both base64-encoded) - let nonce_b64 = BASE64.encode(&nonce); + let nonce_b64 = BASE64.encode(nonce); let ciphertext_b64 = BASE64.encode(&ciphertext); Ok(format!("{}:{}", nonce_b64, ciphertext_b64)) diff --git a/crates/worker/src/service.rs b/crates/worker/src/service.rs index ff096b2..4cd81c4 100644 --- a/crates/worker/src/service.rs +++ b/crates/worker/src/service.rs @@ -443,6 +443,7 @@ impl WorkerService { /// 3. Wait for in-flight tasks with timeout /// 4. Close MQ connection /// 5. Close DB connection + /// /// Verify which runtime versions are available on this host/container. /// /// Runs each version's verification commands (from `distributions` JSONB) @@ -634,7 +635,7 @@ impl WorkerService { shutdown_timeout ); - let timeout_duration = Duration::from_secs(shutdown_timeout as u64); + let timeout_duration = Duration::from_secs(shutdown_timeout); match tokio::time::timeout(timeout_duration, self.wait_for_in_flight_tasks()).await { Ok(_) => info!("All in-flight tasks completed"), Err(_) => warn!("Shutdown timeout reached - some tasks may have been interrupted"), diff --git a/crates/worker/src/version_verify.rs b/crates/worker/src/version_verify.rs index c786d01..f53f10d 100644 --- a/crates/worker/src/version_verify.rs +++ b/crates/worker/src/version_verify.rs @@ -90,7 +90,7 @@ pub async fn verify_all_runtime_versions( let rt_base_name = version .runtime_ref .split('.') - .last() + .next_back() .unwrap_or(&version.runtime_ref) .to_lowercase(); diff --git a/web/knip.json b/web/knip.json index 3f9cd69..2c053a5 100644 --- a/web/knip.json +++ b/web/knip.json @@ -1,6 +1,6 @@ { "$schema": "https://unpkg.com/knip@latest/schema.json", - "entry": ["src/main.tsx", "vite.config.ts"], + "entry": ["src/**/*.{ts,tsx}", "vite.config.ts"], "project": ["src/**/*.{ts,tsx}", "scripts/**/*.js"], "ignore": ["src/api/**", "dist/**", "node_modules/**"] } diff --git a/web/package-lock.json b/web/package-lock.json index 28e66c0..9fb6a15 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -15,8 +15,7 @@ "lucide-react": "^0.562.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-router-dom": "^7.12.0", - "zustand": "^5.0.10" + "react-router-dom": "^7.12.0" }, "devDependencies": { "@eslint/js": "^9.39.1", @@ -1100,9 +1099,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.57.0.tgz", - "integrity": "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], @@ -1114,9 +1113,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.57.0.tgz", - "integrity": "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], @@ -1128,9 +1127,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.57.0.tgz", - "integrity": "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], @@ -1142,9 +1141,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.57.0.tgz", - "integrity": "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], @@ -1156,9 +1155,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.57.0.tgz", - "integrity": "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], @@ -1170,9 +1169,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.57.0.tgz", - "integrity": "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], @@ -1184,9 +1183,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.57.0.tgz", - "integrity": "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], @@ -1198,9 +1197,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.57.0.tgz", - "integrity": "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], @@ -1212,9 +1211,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.57.0.tgz", - "integrity": "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], @@ -1226,9 +1225,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.57.0.tgz", - "integrity": "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], @@ -1240,9 +1239,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.57.0.tgz", - "integrity": "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", "cpu": [ "loong64" ], @@ -1254,9 +1253,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.57.0.tgz", - "integrity": "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ "loong64" ], @@ -1268,9 +1267,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.57.0.tgz", - "integrity": "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ "ppc64" ], @@ -1282,9 +1281,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.57.0.tgz", - "integrity": "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ "ppc64" ], @@ -1296,9 +1295,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.57.0.tgz", - "integrity": "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ "riscv64" ], @@ -1310,9 +1309,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.57.0.tgz", - "integrity": "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ "riscv64" ], @@ -1324,9 +1323,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.57.0.tgz", - "integrity": "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ "s390x" ], @@ -1338,9 +1337,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.57.0.tgz", - "integrity": "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" ], @@ -1352,9 +1351,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.57.0.tgz", - "integrity": "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", "cpu": [ "x64" ], @@ -1366,9 +1365,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.57.0.tgz", - "integrity": "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", "cpu": [ "x64" ], @@ -1380,9 +1379,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.57.0.tgz", - "integrity": "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", "cpu": [ "arm64" ], @@ -1394,9 +1393,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.57.0.tgz", - "integrity": "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", "cpu": [ "arm64" ], @@ -1408,9 +1407,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.57.0.tgz", - "integrity": "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", "cpu": [ "ia32" ], @@ -1422,9 +1421,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.57.0.tgz", - "integrity": "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", "cpu": [ "x64" ], @@ -1436,9 +1435,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.57.0.tgz", - "integrity": "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -1557,7 +1556,7 @@ "version": "19.2.10", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.10.tgz", "integrity": "sha512-WPigyYuGhgZ/cTPRXB2EwUw+XvsRA3GqHlsP4qteqrnnjDrApbS7MxcGr/hke5iUoeB7E/gQtrs9I37zAJ0Vjw==", - "devOptional": true, + "dev": true, "license": "MIT", "peer": true, "dependencies": { @@ -1774,13 +1773,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1890,9 +1889,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -2000,13 +1999,13 @@ } }, "node_modules/axios": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", - "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -2322,7 +2321,7 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/date-fns": { @@ -3430,9 +3429,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -4036,9 +4035,9 @@ } }, "node_modules/rollup": { - "version": "4.57.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.0.tgz", - "integrity": "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { @@ -4052,31 +4051,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.57.0", - "@rollup/rollup-android-arm64": "4.57.0", - "@rollup/rollup-darwin-arm64": "4.57.0", - "@rollup/rollup-darwin-x64": "4.57.0", - "@rollup/rollup-freebsd-arm64": "4.57.0", - "@rollup/rollup-freebsd-x64": "4.57.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", - "@rollup/rollup-linux-arm-musleabihf": "4.57.0", - "@rollup/rollup-linux-arm64-gnu": "4.57.0", - "@rollup/rollup-linux-arm64-musl": "4.57.0", - "@rollup/rollup-linux-loong64-gnu": "4.57.0", - "@rollup/rollup-linux-loong64-musl": "4.57.0", - "@rollup/rollup-linux-ppc64-gnu": "4.57.0", - "@rollup/rollup-linux-ppc64-musl": "4.57.0", - "@rollup/rollup-linux-riscv64-gnu": "4.57.0", - "@rollup/rollup-linux-riscv64-musl": "4.57.0", - "@rollup/rollup-linux-s390x-gnu": "4.57.0", - "@rollup/rollup-linux-x64-gnu": "4.57.0", - "@rollup/rollup-linux-x64-musl": "4.57.0", - "@rollup/rollup-openbsd-x64": "4.57.0", - "@rollup/rollup-openharmony-arm64": "4.57.0", - "@rollup/rollup-win32-arm64-msvc": "4.57.0", - "@rollup/rollup-win32-ia32-msvc": "4.57.0", - "@rollup/rollup-win32-x64-gnu": "4.57.0", - "@rollup/rollup-win32-x64-msvc": "4.57.0", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, @@ -4699,35 +4698,6 @@ "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } - }, - "node_modules/zustand": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.10.tgz", - "integrity": "sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==", - "license": "MIT", - "engines": { - "node": ">=12.20.0" - }, - "peerDependencies": { - "@types/react": ">=18.0.0", - "immer": ">=9.0.6", - "react": ">=18.0.0", - "use-sync-external-store": ">=1.2.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "immer": { - "optional": true - }, - "react": { - "optional": true - }, - "use-sync-external-store": { - "optional": true - } - } } } } diff --git a/web/package.json b/web/package.json index a8f6f03..e6b5789 100644 --- a/web/package.json +++ b/web/package.json @@ -20,8 +20,7 @@ "lucide-react": "^0.562.0", "react": "^19.2.0", "react-dom": "^19.2.0", - "react-router-dom": "^7.12.0", - "zustand": "^5.0.10" + "react-router-dom": "^7.12.0" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/web/src/main.tsx b/web/src/main.tsx index 9223d6b..cb1ebd2 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -3,7 +3,7 @@ import { createRoot } from "react-dom/client"; import "./index.css"; import "./lib/api-config"; import { initializeApiWrapper } from "./lib/api-wrapper"; -import App from "./App.tsx"; +import App from "./App"; // Initialize API wrapper for token refresh initializeApiWrapper();