Files
redis-gui-foundation/crates/redis-core/src/connection.rs
Senior Frontend Engineer 8d50243d36 feat(desktop): add redis gui foundation baseline
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-28 10:39:40 +00:00

239 lines
6.3 KiB
Rust

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<String>,
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<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct ConnectionTestResult {
pub selected_database: i64,
pub authenticated_as: Option<String>,
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<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CommandExecutionResult {
pub command: String,
pub arguments: Vec<String>,
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<String>,
#[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<String>,
pub keys: Vec<RedisKeyMetadata>,
}
#[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<RedisFieldValueEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RedisValueContent {
String { value: String },
Binary { bytes: Vec<u8> },
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum RedisValueData {
Missing,
String { value: RedisValueContent },
Hash { entries: Vec<RedisFieldValueEntry> },
List { items: Vec<RedisValueContent> },
Set { members: Vec<RedisValueContent> },
SortedSet { entries: Vec<RedisSortedSetEntry> },
Stream { entries: Vec<RedisStreamEntry> },
}
#[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<u8> },
Array { items: Vec<RedisResponse> },
}
#[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
}