vs_daemon/config.rs
1//! Filesystem layout: where the daemon keeps state on disk.
2//!
3//! ```text
4//! ~/.vibesurfer/
5//! daemon.sock # the IPC socket
6//! active-session # one-line session id
7//! state.db # SQLite, WAL mode
8//! key # AES-256 fallback if OS keyring unavailable
9//! log/ # rotating tracing output (M5+)
10//! captures/ # screenshot output paths (M5+)
11//! ```
12
13use std::path::{Path, PathBuf};
14
15/// Daemon-side filesystem layout.
16#[derive(Debug, Clone)]
17pub struct Paths {
18 /// Root directory; usually `$HOME/.vibesurfer`.
19 pub root: PathBuf,
20}
21
22impl Paths {
23 /// Construct from a custom root (tests use a temp dir).
24 #[must_use]
25 pub fn at(root: impl Into<PathBuf>) -> Self {
26 Self { root: root.into() }
27 }
28
29 /// Conventional location: `$HOME/.vibesurfer`. Falls back to the
30 /// current directory if `$HOME` is unset (rare; CI containers).
31 #[must_use]
32 pub fn home() -> Self {
33 let root = std::env::var_os("HOME").map_or_else(
34 || PathBuf::from(".vibesurfer"),
35 |h| Path::new(&h).join(".vibesurfer"),
36 );
37 Self::at(root)
38 }
39
40 #[must_use]
41 pub fn socket(&self) -> PathBuf {
42 self.root.join("daemon.sock")
43 }
44
45 /// PID file for the running daemon. Written by `vs serve` on startup
46 /// and removed on graceful shutdown. `vs serve --stop` reads it.
47 #[must_use]
48 pub fn pid_file(&self) -> PathBuf {
49 self.root.join("daemon.pid")
50 }
51
52 #[must_use]
53 pub fn db(&self) -> PathBuf {
54 self.root.join("state.db")
55 }
56
57 #[must_use]
58 pub fn active_session(&self) -> PathBuf {
59 self.root.join("active-session")
60 }
61
62 #[must_use]
63 pub fn key_file(&self) -> PathBuf {
64 self.root.join("key")
65 }
66
67 /// Where the daemon writes screenshot PNGs from `vs_capture`.
68 /// Defaults to `<root>/captures`. Overridable per-process via the
69 /// `VS_CAPTURES_DIR` environment variable.
70 #[must_use]
71 pub fn captures(&self) -> PathBuf {
72 if let Some(p) = std::env::var_os("VS_CAPTURES_DIR") {
73 return PathBuf::from(p);
74 }
75 self.root.join("captures")
76 }
77
78 /// Ensure the root directory exists.
79 pub fn ensure_root(&self) -> std::io::Result<()> {
80 std::fs::create_dir_all(&self.root)
81 }
82}