feat(protocol): JSON-RPC method param/result types

This commit is contained in:
2026-05-25 11:31:56 +02:00
parent e8f5846cec
commit bd926061bf
2 changed files with 149 additions and 0 deletions
+1
View File
@@ -3,6 +3,7 @@
pub mod config;
pub mod error;
pub mod kdl_parse;
pub mod rpc;
pub mod state;
pub use config::{RestartConfig, RestartPolicy, ServerConfig, StopConfig};
+148
View File
@@ -0,0 +1,148 @@
use crate::ServerState;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerSummary {
pub name: String,
pub state: ServerState,
#[serde(skip_serializing_if = "Option::is_none")]
pub pid: Option<u32>,
pub port: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub uptime_secs: Option<u64>,
pub restart_count: u32,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_exit: Option<i32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusDetail {
#[serde(flatten)]
pub summary: ServerSummary,
pub recent_transitions: Vec<StateTransition>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StateTransition {
pub from: ServerState,
pub to: ServerState,
pub at_unix_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum NameOrAll {
All { all: bool },
Name { name: String },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusParams {
pub name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StartResult {
pub started: Vec<String>,
pub already_running: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StopResult {
pub stopped: Vec<String>,
pub not_running: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RestartResult {
pub restarted: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReloadResult {
pub added: Vec<String>,
pub removed: Vec<String>,
pub changed: Vec<String>,
pub unchanged: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogsParams {
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tail: Option<u32>,
#[serde(default)]
pub follow: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogsSubscribed {
pub subscription_id: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogsCancelParams {
pub subscription_id: u64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum LogStream {
Stdout,
Stderr,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogLine {
pub subscription_id: u64,
pub name: String,
pub stream: LogStream,
pub line: String,
pub ts_unix_ms: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEnd {
pub subscription_id: u64,
}
pub mod methods {
pub const LIST: &str = "list";
pub const STATUS: &str = "status";
pub const START: &str = "start";
pub const STOP: &str = "stop";
pub const RESTART: &str = "restart";
pub const RELOAD: &str = "reload";
pub const LOGS: &str = "logs";
pub const LOGS_CANCEL: &str = "logs_cancel";
}
pub mod notifications {
pub const LOG: &str = "log";
pub const LOG_END: &str = "log_end";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn name_or_all_round_trips_name() {
let v: NameOrAll = serde_json::from_str(r#"{"name":"foo"}"#).unwrap();
match v {
NameOrAll::Name { name } => assert_eq!(name, "foo"),
_ => panic!("expected Name variant"),
}
}
#[test]
fn name_or_all_round_trips_all() {
let v: NameOrAll = serde_json::from_str(r#"{"all":true}"#).unwrap();
match v {
NameOrAll::All { all } => assert!(all),
_ => panic!("expected All variant"),
}
}
}