From 355d0debda453ebd85fbbd1c4da681b0a9b3e8fe Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Mon, 25 May 2026 11:23:57 +0200 Subject: [PATCH] feat(protocol): ServerConfig + ConfigError + RpcErrorCode --- crates/xy-protocol/src/config.rs | 20 +++++++++++++++++ crates/xy-protocol/src/error.rs | 37 ++++++++++++++++++++++++++++++++ crates/xy-protocol/src/lib.rs | 4 +++- 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 crates/xy-protocol/src/error.rs diff --git a/crates/xy-protocol/src/config.rs b/crates/xy-protocol/src/config.rs index f520339..a4cab81 100644 --- a/crates/xy-protocol/src/config.rs +++ b/crates/xy-protocol/src/config.rs @@ -68,6 +68,26 @@ impl Default for StopConfig { } } +use std::collections::BTreeMap; +use std::path::PathBuf; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ServerConfig { + pub name: String, + pub command: PathBuf, + #[serde(default)] + pub args: Vec, + pub port: u16, + #[serde(default)] + pub env: BTreeMap, + #[serde(default)] + pub working_dir: Option, + #[serde(default)] + pub restart: RestartConfig, + #[serde(default)] + pub stop: StopConfig, +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/xy-protocol/src/error.rs b/crates/xy-protocol/src/error.rs new file mode 100644 index 0000000..4a0ffba --- /dev/null +++ b/crates/xy-protocol/src/error.rs @@ -0,0 +1,37 @@ +use std::path::PathBuf; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ConfigError { + #[error("failed to read {path}: {source}")] + Io { path: PathBuf, #[source] source: std::io::Error }, + + #[error("failed to parse KDL in {path}: {message}")] + Parse { path: PathBuf, message: String }, + + #[error("missing required field `{field}` in {path}")] + MissingField { path: PathBuf, field: &'static str }, + + #[error("invalid value for `{field}` in {path}: {message}")] + InvalidValue { path: PathBuf, field: &'static str, message: String }, + + #[error("duplicate port {port} declared by both `{name_a}` and `{name_b}`")] + DuplicatePort { name_a: String, name_b: String, port: u16 }, + + #[error("server name `{name}` contains invalid characters (allowed: a-z, 0-9, '-', '_')")] + InvalidName { name: String }, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RpcErrorCode { + ServerNotFound = -32001, + PortConflict = -32002, + ConfigInvalid = -32003, + AlreadyRunning = -32004, + NotRunning = -32005, + SpawnFailed = -32006, +} + +impl RpcErrorCode { + pub fn as_i32(self) -> i32 { self as i32 } +} diff --git a/crates/xy-protocol/src/lib.rs b/crates/xy-protocol/src/lib.rs index 246cdfd..6c933ad 100644 --- a/crates/xy-protocol/src/lib.rs +++ b/crates/xy-protocol/src/lib.rs @@ -1,7 +1,9 @@ //! Wire types and config schema shared between the xy daemon and CLI. pub mod config; +pub mod error; pub mod state; -pub use config::{RestartConfig, RestartPolicy, StopConfig}; +pub use config::{RestartConfig, RestartPolicy, ServerConfig, StopConfig}; +pub use error::{ConfigError, RpcErrorCode}; pub use state::ServerState;