use serde::{Deserialize, Serialize}; use crate::BackendError; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct ConnectionProfileDraft { pub display_name: String, pub target: ConnectionTarget, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct ConnectionTarget { pub host: String, pub port: u16, pub database: i64, pub username: Option, pub tls_mode: TlsMode, } impl Default for ConnectionTarget { fn default() -> Self { Self { host: "127.0.0.1".to_string(), port: 6379, database: 0, username: None, tls_mode: TlsMode::Disabled, } } } impl ConnectionTarget { pub fn validate(&self) -> Result<(), BackendError> { if self.host.trim().is_empty() { return Err(BackendError::invalid_connection_config( "Redis host must not be empty.", )); } if self.database < 0 { return Err(BackendError::invalid_connection_config( "Redis database must be zero or a positive integer.", )); } Ok(()) } } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisConnectionRequest { pub target: ConnectionTarget, pub password: Option, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct ConnectionTestResult { pub selected_database: i64, pub authenticated_as: Option, pub round_trip_status: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisCommandRequest { pub connection: RedisConnectionRequest, pub command: String, #[serde(default)] pub arguments: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct CommandExecutionResult { pub command: String, pub arguments: Vec, pub database: i64, pub response: RedisResponse, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyBrowseRequest { pub connection: RedisConnectionRequest, #[serde(default = "default_scan_cursor")] pub cursor: String, #[serde(default)] pub pattern: Option, #[serde(default = "default_scan_page_size")] pub page_size: u32, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyBrowseResult { pub database: i64, pub submitted_cursor: String, pub next_cursor: String, pub has_more: bool, pub page_size: u32, pub pattern: Option, pub keys: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyMetadataRequest { pub connection: RedisConnectionRequest, pub key: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisValueReadRequest { pub connection: RedisConnectionRequest, pub key: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisValueWriteRequest { pub connection: RedisConnectionRequest, pub key: String, pub value: RedisValueWriteInput, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyTtlUpdateRequest { pub connection: RedisConnectionRequest, pub key: String, pub operation: RedisKeyTtlUpdate, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyMetadata { pub name: String, pub database: i64, pub exists: bool, pub key_type: String, pub ttl: RedisKeyTtl, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisKeyTtl { Persistent, Missing, ExpiresInMillis { value: i64 }, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisValueRecord { pub metadata: RedisKeyMetadata, pub data: RedisValueData, pub write_capability: RedisValueWriteCapability, pub ttl_write_supported: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisKeyTtlUpdateResult { pub metadata: RedisKeyMetadata, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisFieldValueEntry { pub field: RedisValueContent, pub value: RedisValueContent, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisSortedSetEntry { pub member: RedisValueContent, pub score: String, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct RedisStreamEntry { pub id: String, pub fields: Vec, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisValueContent { String { value: String }, Binary { bytes: Vec }, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisValueData { Missing, String { value: RedisValueContent }, Hash { entries: Vec }, List { items: Vec }, Set { members: Vec }, SortedSet { entries: Vec }, Stream { entries: Vec }, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisValueWriteInput { String { value: String }, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum RedisValueWriteCapability { None, ReplaceString, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisKeyTtlUpdate { Persist, ExpiresInMillis { value: u64 }, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[serde(tag = "kind", rename_all = "snake_case")] pub enum RedisResponse { Null, Integer { value: i64 }, String { value: String }, Binary { bytes: Vec }, Array { items: Vec }, } #[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "snake_case")] pub enum TlsMode { Disabled, Preferred, Required, } fn default_scan_cursor() -> String { "0".to_string() } fn default_scan_page_size() -> u32 { 100 }