Skip to main content

redisctl_core/
lib.rs

1//! # redisctl-core
2//!
3//! Layer 2: Higher-level interface on top of redis-cloud and redis-enterprise clients.
4//!
5//! This crate provides:
6//! - **Unified error handling** - CoreError wrapping both platform errors
7//! - **Client resolution** - Shared profile, credential, endpoint, and TLS handling
8//! - **Progress callbacks** - For Cloud's async task polling
9//! - **Module resolution** - Validate Enterprise modules before creation
10//! - **Workflows** - Multi-step operations (create + wait, etc.)
11//!
12//! ## Philosophy
13//!
14//! **Don't rebuild Layer 1. Use it and add value.**
15//!
16//! - Simple operations: Use Layer 1 directly (`redis_cloud::DatabaseHandler`, etc.)
17//! - Operations with progress: Use Layer 2 workflows
18//! - Operations with validation: Use Layer 2 helpers
19//!
20//! # Architecture
21//!
22//! ```text
23//! ┌─────────────────────────────────────────────────────────────────┐
24//! │                    Layer 3: Consumers                           │
25//! │           CLI (redisctl)        MCP (redisctl-mcp)             │
26//! └──────────────────────────┬──────────────────────────────────────┘
27//!                            │
28//!                            ▼
29//! ┌─────────────────────────────────────────────────────────────────┐
30//! │                 Layer 2: redisctl-core                          │
31//! │  - Unified errors (CoreError)                                   │
32//! │  - Client resolution (ClientResolver)                           │
33//! │  - Progress callbacks (poll_task)                               │
34//! │  - Module resolution (resolve_modules)                          │
35//! │  - Workflows (create_and_wait, etc.)                            │
36//! └──────────────────────────┬──────────────────────────────────────┘
37//!                            │
38//!                            ▼
39//! ┌─────────────────────────────────────────────────────────────────┐
40//! │               Layer 1: Raw API Clients                          │
41//! │         redis-cloud              redis-enterprise               │
42//! └─────────────────────────────────────────────────────────────────┘
43//! ```
44//!
45//! # Example Usage
46//!
47//! ```rust,ignore
48//! use redis_cloud::{CloudClient, DatabaseHandler};
49//! use redisctl_core::{poll_task, ProgressEvent};
50//! use std::time::Duration;
51//!
52//! // Simple operation: use Layer 1 directly
53//! let handler = DatabaseHandler::new(client.clone());
54//! let databases = handler.list(subscription_id).await?;
55//!
56//! // Operation with progress: use Layer 2
57//! let task = handler.create(subscription_id, &request).await?;
58//! let completed = poll_task(
59//!     &client,
60//!     &task.task_id.unwrap(),
61//!     Duration::from_secs(600),
62//!     Duration::from_secs(10),
63//!     Some(Box::new(|event| {
64//!         if let ProgressEvent::Polling { status, elapsed, .. } = event {
65//!             println!("Status: {} ({:.0}s)", status, elapsed.as_secs());
66//!         }
67//!     })),
68//! ).await?;
69//! ```
70
71/// `User-Agent` sent by every redisctl HTTP client.
72///
73/// The Redis Cloud API recognises the `redisctl/` prefix as a trusted client for some operations
74/// (free-tier provisioning among them), so all consumers — CLI and MCP alike — must send it.
75pub const USER_AGENT: &str = concat!("redisctl/", env!("CARGO_PKG_VERSION"));
76
77/// Bound and flatten text from an upstream service before it reaches an error message.
78///
79/// Those messages are read by agents as well as people, so third-party text must not arrive with
80/// newlines or control characters, or at arbitrary length.
81pub(crate) fn bound_upstream_text(text: &str) -> String {
82    const MAX: usize = 200;
83    let flattened: String = text
84        .chars()
85        .map(|c| if c.is_control() { ' ' } else { c })
86        .take(MAX)
87        .collect();
88    let trimmed = flattened.trim().to_string();
89    if text.chars().count() > MAX {
90        format!("{trimmed}…")
91    } else {
92        trimmed
93    }
94}
95
96pub mod auth;
97pub mod clients;
98pub mod config;
99pub mod error;
100pub mod progress;
101
102pub mod cloud;
103pub mod enterprise;
104
105// Re-export commonly used items
106pub use auth::{
107    AuthError, CapiKey, CloudAuthenticator, DeviceAuthorization, DeviceFlowClient,
108    LoopbackFlowClient, MintedCredentials, SmAccount, SmApiClient, SmUser, TokenSet,
109};
110pub use error::{CoreError, Result};
111pub use progress::{ProgressCallback, ProgressEvent, poll_task};
112
113// Re-export config types for convenience
114pub use clients::{
115    ClientResolutionError, ClientResolver, ResolvedCloudConnection, ResolvedEnterpriseConnection,
116};
117pub use config::{
118    CloudAuthConfig, Config, ConfigError, CredentialStorage, CredentialStore, DeploymentType,
119    EnvironmentOverrides, Profile, ProfileCredentials,
120};
121
122// Re-export Layer 1 for convenience (but consumers can also import directly)
123pub use redis_cloud;
124pub use redis_enterprise;