use serde::{Deserialize, Serialize}; // ── IPC envelope types ────────────────────────────────────────────────────── /// Request from TypeScript (via stdin) #[derive(Debug, Deserialize)] pub struct IpcRequest { pub id: String, pub method: String, pub params: serde_json::Value, } /// Response to TypeScript (via stdout) #[derive(Debug, Serialize)] pub struct IpcResponse { pub id: String, pub success: bool, #[serde(skip_serializing_if = "Option::is_none")] pub result: Option, #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, } impl IpcResponse { pub fn ok(id: String, result: serde_json::Value) -> Self { Self { id, success: true, result: Some(result), error: None } } pub fn ok_void(id: String) -> Self { Self { id, success: true, result: None, error: None } } pub fn err(id: String, error: String) -> Self { Self { id, success: false, result: None, error: Some(error) } } } /// Stream chunk (Rust → TS, before final response) #[derive(Debug, Serialize)] pub struct IpcStreamChunk { pub id: String, pub stream: bool, pub data: serde_json::Value, } /// Unsolicited event (Rust → TS) #[derive(Debug, Serialize)] pub struct IpcEvent { pub event: String, pub data: serde_json::Value, } // ── Filesystem domain types ───────────────────────────────────────────────── #[derive(Debug, Serialize, Deserialize, Clone)] pub struct FileStats { pub size: u64, pub birthtime: String, pub mtime: String, pub atime: String, #[serde(rename = "isFile")] pub is_file: bool, #[serde(rename = "isDirectory")] pub is_directory: bool, #[serde(rename = "isSymbolicLink")] pub is_symbolic_link: bool, pub mode: u32, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct DirectoryEntry { pub name: String, pub path: String, #[serde(rename = "isFile")] pub is_file: bool, #[serde(rename = "isDirectory")] pub is_directory: bool, #[serde(rename = "isSymbolicLink")] pub is_symbolic_link: bool, #[serde(skip_serializing_if = "Option::is_none")] pub stats: Option, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WatchEvent { #[serde(rename = "type")] pub event_type: String, pub path: String, pub timestamp: String, #[serde(skip_serializing_if = "Option::is_none")] pub stats: Option, } // ── Command parameter types ───────────────────────────────────────────────── #[derive(Debug, Deserialize)] pub struct ReadFileParams { pub path: String, pub encoding: Option, } #[derive(Debug, Deserialize)] pub struct WriteFileParams { pub path: String, pub content: String, pub atomic: Option, pub mode: Option, pub encoding: Option, } #[derive(Debug, Deserialize)] pub struct AppendFileParams { pub path: String, pub content: String, pub encoding: Option, } #[derive(Debug, Deserialize)] pub struct PathParams { pub path: String, } #[derive(Debug, Deserialize)] pub struct CopyMoveParams { pub from: String, pub to: String, pub overwrite: Option, #[serde(rename = "preserveTimestamps")] pub preserve_timestamps: Option, } #[derive(Debug, Deserialize)] pub struct ListDirectoryParams { pub path: String, pub recursive: Option, #[serde(rename = "includeStats")] pub include_stats: Option, pub filter: Option, } #[derive(Debug, Deserialize)] pub struct CreateDirectoryParams { pub path: String, pub recursive: Option, pub mode: Option, } #[derive(Debug, Deserialize)] pub struct DeleteDirectoryParams { pub path: String, pub recursive: Option, } #[derive(Debug, Deserialize)] pub struct WatchParams { pub path: String, pub id: String, pub recursive: Option, } // ── Batch operations ──────────────────────────────────────────────────────── #[derive(Debug, Deserialize)] pub struct BatchOp { #[serde(rename = "type")] pub op_type: String, pub path: String, #[serde(rename = "targetPath")] pub target_path: Option, pub content: Option, pub encoding: Option, pub atomic: Option, pub mode: Option, pub overwrite: Option, pub recursive: Option, } #[derive(Debug, Serialize)] pub struct BatchResult { pub index: usize, pub success: bool, #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, } #[derive(Debug, Deserialize)] pub struct BatchParams { pub operations: Vec, } // ── Transaction operations ────────────────────────────────────────────────── #[derive(Debug, Deserialize)] pub struct TransactionOp { #[serde(rename = "type")] pub op_type: String, pub path: String, #[serde(rename = "targetPath")] pub target_path: Option, pub content: Option, pub encoding: Option, } #[derive(Debug, Deserialize)] pub struct TransactionParams { pub operations: Vec, } // ── Path operations ───────────────────────────────────────────────────────── #[derive(Debug, Deserialize)] pub struct NormalizePathParams { pub path: String, } #[derive(Debug, Deserialize)] pub struct JoinPathParams { pub segments: Vec, } // ── Streaming operations ──────────────────────────────────────────────────── #[derive(Debug, Deserialize)] pub struct ReadFileStreamParams { pub path: String, #[serde(rename = "chunkSize")] pub chunk_size: Option, } #[derive(Debug, Deserialize)] pub struct WriteStreamBeginParams { pub path: String, pub atomic: Option, pub mode: Option, } #[derive(Debug, Deserialize)] pub struct WriteStreamChunkParams { #[serde(rename = "streamId")] pub stream_id: String, pub data: String, pub last: bool, }