opencode_cloud_core/config/
schema.rs1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11#[serde(deny_unknown_fields)]
12pub struct Config {
13 pub version: u32,
15
16 #[serde(default = "default_opencode_web_port")]
18 pub opencode_web_port: u16,
19
20 #[serde(default = "default_bind")]
24 pub bind: String,
25
26 #[serde(default = "default_auto_restart")]
28 pub auto_restart: bool,
29
30 #[serde(default = "default_boot_mode")]
34 pub boot_mode: String,
35
36 #[serde(default = "default_restart_retries")]
38 pub restart_retries: u32,
39
40 #[serde(default = "default_restart_delay")]
42 pub restart_delay: u32,
43}
44
45fn default_opencode_web_port() -> u16 {
46 3000
47}
48
49fn default_bind() -> String {
50 "localhost".to_string()
51}
52
53fn default_auto_restart() -> bool {
54 true
55}
56
57fn default_boot_mode() -> String {
58 "user".to_string()
59}
60
61fn default_restart_retries() -> u32 {
62 3
63}
64
65fn default_restart_delay() -> u32 {
66 5
67}
68
69impl Default for Config {
70 fn default() -> Self {
71 Self {
72 version: 1,
73 opencode_web_port: default_opencode_web_port(),
74 bind: default_bind(),
75 auto_restart: default_auto_restart(),
76 boot_mode: default_boot_mode(),
77 restart_retries: default_restart_retries(),
78 restart_delay: default_restart_delay(),
79 }
80 }
81}
82
83impl Config {
84 pub fn new() -> Self {
86 Self::default()
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_default_config() {
96 let config = Config::default();
97 assert_eq!(config.version, 1);
98 assert_eq!(config.opencode_web_port, 3000);
99 assert_eq!(config.bind, "localhost");
100 assert!(config.auto_restart);
101 assert_eq!(config.boot_mode, "user");
102 assert_eq!(config.restart_retries, 3);
103 assert_eq!(config.restart_delay, 5);
104 }
105
106 #[test]
107 fn test_serialize_deserialize_roundtrip() {
108 let config = Config::default();
109 let json = serde_json::to_string(&config).unwrap();
110 let parsed: Config = serde_json::from_str(&json).unwrap();
111 assert_eq!(config, parsed);
112 }
113
114 #[test]
115 fn test_deserialize_with_missing_optional_fields() {
116 let json = r#"{"version": 1}"#;
117 let config: Config = serde_json::from_str(json).unwrap();
118 assert_eq!(config.version, 1);
119 assert_eq!(config.opencode_web_port, 3000);
120 assert_eq!(config.bind, "localhost");
121 assert!(config.auto_restart);
122 assert_eq!(config.boot_mode, "user");
123 assert_eq!(config.restart_retries, 3);
124 assert_eq!(config.restart_delay, 5);
125 }
126
127 #[test]
128 fn test_serialize_deserialize_roundtrip_with_service_fields() {
129 let config = Config {
130 version: 1,
131 opencode_web_port: 9000,
132 bind: "0.0.0.0".to_string(),
133 auto_restart: false,
134 boot_mode: "system".to_string(),
135 restart_retries: 5,
136 restart_delay: 10,
137 };
138 let json = serde_json::to_string(&config).unwrap();
139 let parsed: Config = serde_json::from_str(&json).unwrap();
140 assert_eq!(config, parsed);
141 assert_eq!(parsed.boot_mode, "system");
142 assert_eq!(parsed.restart_retries, 5);
143 assert_eq!(parsed.restart_delay, 10);
144 }
145
146 #[test]
147 fn test_reject_unknown_fields() {
148 let json = r#"{"version": 1, "unknown_field": "value"}"#;
149 let result: Result<Config, _> = serde_json::from_str(json);
150 assert!(result.is_err());
151 }
152}