1#[derive(thiserror::Error, Debug)]
2pub enum Error {
3 #[error(transparent)]
4 Db(#[from] nostr_db::Error),
5 #[error(transparent)]
6 Io(#[from] std::io::Error),
7 #[error(transparent)]
8 Config(#[from] config::ConfigError),
9 #[error(transparent)]
10 Notify(#[from] notify::Error),
11 #[error(transparent)]
12 Json(#[from] serde_json::Error),
13 #[error("invalid: {0}")]
14 Invalid(String),
15 #[error("{0}")]
16 Message(String),
17 #[error("{0}")]
18 Str(&'static str),
19}
20
21impl actix_web::ResponseError for Error {}
22
23pub type Result<T, E = Error> = core::result::Result<T, E>;
24
25mod app;
26pub mod duration;
27mod extension;
28mod hash;
29mod list;
30pub mod message;
31mod reader;
32mod server;
33mod session;
34pub mod setting;
35mod subscriber;
36mod writer;
37
38pub use metrics;
39pub use nostr_db as db;
40pub use {
41 app::*, extension::*, list::List, reader::Reader, server::Server, session::Session,
42 setting::Setting, subscriber::Subscriber, writer::Writer,
43};
44
45#[cfg(test)]
46pub fn temp_data_path(p: &str) -> anyhow::Result<tempfile::TempDir> {
47 Ok(tempfile::Builder::new()
48 .prefix(&format!("nostr-relay-test-db-{}", p))
49 .tempdir()?)
50}
51
52#[cfg(test)]
53pub fn create_test_app(db_path: &str) -> anyhow::Result<App> {
54 Ok(App::create(
55 None,
56 false,
57 None,
58 Some(temp_data_path(db_path)?),
59 )?)
60}
61
62#[cfg(test)]
63mod lib_tests {
64 use super::*;
65 use actix_web::http::StatusCode;
66 use actix_web::ResponseError;
67
68 #[test]
69 fn test_error_display() {
70 let db_error = Error::Db(nostr_db::Error::Io(std::io::Error::new(
71 std::io::ErrorKind::Other,
72 "db error",
73 )));
74 assert_eq!(format!("{}", db_error), "io: db error");
75
76 let io_error = Error::Io(std::io::Error::new(
77 std::io::ErrorKind::NotFound,
78 "file not found",
79 ));
80 assert_eq!(format!("{}", io_error), "file not found");
81
82 let config_error = Error::Config(config::ConfigError::Message("config error".to_string()));
83 assert_eq!(format!("{}", config_error), "config error");
84
85 let notify_error = Error::Notify(notify::Error::new(notify::ErrorKind::PathNotFound));
86 assert_eq!(format!("{}", notify_error), "No path was found.");
87
88 let json_error = Error::Json(serde_json::from_str::<serde_json::Value>("{").unwrap_err());
89 assert!(format!("{}", json_error).contains("EOF while parsing an object"));
90
91 let invalid_error = Error::Invalid("invalid input".to_string());
92 assert_eq!(format!("{}", invalid_error), "invalid: invalid input");
93
94 let message_error = Error::Message("custom message".to_string());
95 assert_eq!(format!("{}", message_error), "custom message");
96
97 let str_error = Error::Str("static string error");
98 assert_eq!(format!("{}", str_error), "static string error");
99 }
100
101 #[test]
102 fn test_error_response_error() {
103 let error = Error::Invalid("test".to_string());
104 let response = error.error_response();
105 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
106 }
107
108 #[test]
109 fn test_temp_data_path() -> anyhow::Result<()> {
110 let temp_dir = temp_data_path("test_temp_data_path")?;
111 assert!(temp_dir.path().exists());
112 assert!(temp_dir.path().is_dir());
113 Ok(())
114 }
115
116 #[actix_web::test]
117 async fn test_create_test_app() -> anyhow::Result<()> {
118 let _app = create_test_app("test_create_test_app")?;
119 Ok(())
122 }
123}