Skip to main content

saola_user_facing_errors/
common.rs

1use crate::UserFacingError;
2use serde::Serialize;
3use std::fmt::Display;
4use user_facing_error_macros::*;
5
6#[derive(Debug, UserFacingError, Serialize)]
7#[user_facing(
8    code = "P1000",
9    message = "\
10Authentication failed against database server, the provided database credentials for `{database_user}` are not valid.
11
12Please make sure to provide valid database credentials for the database server at the configured address."
13)]
14// **Notes**: Might vary for different data source, For example, SQLite has no concept of user accounts, and instead relies on the file system for all database permissions. This makes enforcing storage quotas difficult and enforcing user permissions impossible.
15pub struct IncorrectDatabaseCredentials {
16    /// Database user name
17    pub database_user: String,
18}
19
20#[derive(Debug, UserFacingError, Serialize)]
21#[user_facing(
22    code = "P1001",
23    message = "\
24Can't reach database server at `{database_location}`
25
26Please make sure your database server is running at `{database_location}`."
27)]
28pub struct DatabaseNotReachable {
29    pub database_location: String,
30}
31
32#[derive(Debug, UserFacingError, Serialize)]
33#[user_facing(
34    code = "P1002",
35    message = "\
36The database server was reached but timed out.
37
38Please try again.
39
40Please make sure your database server is running at the configured address.
41
42Context: {context}
43"
44)]
45pub struct DatabaseTimeout {
46    /// Extra context
47    pub context: String,
48}
49
50#[derive(Debug, Serialize)]
51pub struct DatabaseDoesNotExist {
52    pub database_name: String,
53}
54
55impl UserFacingError for DatabaseDoesNotExist {
56    const ERROR_CODE: &'static str = "P1003";
57
58    fn message(&self) -> String {
59        format!("Database `{}` does not exist", self.database_name)
60    }
61}
62
63#[derive(Debug, UserFacingError, Serialize)]
64#[user_facing(
65    code = "P1008",
66    message = "Socket timeout (the database failed to respond to a query within the configured timeout{extra_hint})."
67)]
68pub struct DatabaseOperationTimeout {
69    /// Extra hint
70    pub extra_hint: String,
71}
72
73#[derive(Debug, UserFacingError, Serialize)]
74#[user_facing(
75    code = "P1009",
76    message = "Database `{database_name}` already exists on the database server"
77)]
78pub struct DatabaseAlreadyExists {
79    /// Database name, append `database_schema_name` when applicable
80    /// `database_schema_name`: Database schema name (For Postgres for example)
81    pub database_name: String,
82}
83
84#[derive(Debug, UserFacingError, Serialize)]
85#[user_facing(code = "P1010", message = "User was denied access on the database `{database_name}`")]
86pub struct DatabaseAccessDenied {
87    /// Database name, append `database_schema_name` when applicable
88    /// `database_schema_name`: Database schema name (For Postgres for example)
89    pub database_name: String,
90}
91
92#[derive(Debug, UserFacingError, Serialize)]
93#[user_facing(code = "P1011", message = "Error opening a TLS connection: {message}")]
94pub struct TlsConnectionError {
95    pub message: String,
96}
97
98#[derive(Debug, UserFacingError, Serialize)]
99#[user_facing(code = "P1012", message = "{full_error}")]
100pub struct SchemaParserError {
101    pub full_error: String,
102}
103
104#[derive(Debug, UserFacingError, Serialize)]
105#[user_facing(code = "P1013", message = "The provided database string is invalid. {details}")]
106pub struct InvalidConnectionString {
107    pub details: String,
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
111pub enum ModelKind {
112    Table,
113}
114
115impl Display for ModelKind {
116    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117        match self {
118            Self::Table => write!(f, "table"),
119        }
120    }
121}
122
123#[derive(Debug, UserFacingError, Serialize)]
124#[user_facing(
125    code = "P1014",
126    message = "The underlying {kind} for model `{model}` does not exist."
127)]
128pub struct InvalidModel {
129    pub model: String,
130    pub kind: ModelKind,
131}
132
133#[derive(Debug, UserFacingError, Serialize)]
134#[user_facing(
135    code = "P1015",
136    message = "Your Prisma schema is using features that are not supported for the version of the database.\nDatabase version: {database_version}\nErrors:\n{errors}"
137)]
138pub struct DatabaseVersionIncompatibility {
139    pub database_version: String,
140    pub errors: String,
141}
142
143#[derive(Debug, UserFacingError, Serialize)]
144#[user_facing(
145    code = "P1016",
146    message = "Your raw query had an incorrect number of parameters. Expected: `{expected}`, actual: `{actual}`."
147)]
148pub struct IncorrectNumberOfParameters {
149    pub expected: usize,
150    pub actual: usize,
151}
152
153#[derive(Debug, SimpleUserFacingError)]
154#[user_facing(code = "P1017", message = "Server has closed the connection.")]
155pub struct ConnectionClosed;
156
157#[derive(Debug, UserFacingError, Serialize)]
158#[user_facing(code = "P1018", message = "{message}")]
159pub struct TransactionAlreadyClosed {
160    pub message: String,
161}
162
163#[derive(Debug, UserFacingError, Serialize)]
164#[user_facing(code = "P1019", message = "{message}")]
165pub struct UnsupportedFeatureError {
166    pub message: String,
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172    use crate::UserFacingError;
173
174    #[test]
175    fn database_does_not_exist_formats_properly() {
176        let sqlite_err = DatabaseDoesNotExist {
177            database_name: "dev.db".into(),
178        };
179
180        assert_eq!(sqlite_err.message(), "Database `dev.db` does not exist");
181    }
182}