1use spacetimedb_lib::db::error::{AuthError, RelationError};
2use spacetimedb_lib::operator::OpLogic;
3use spacetimedb_sats::{AlgebraicType, AlgebraicValue};
4use std::fmt;
5use thiserror::Error;
6
7use crate::expr::SourceId;
8
9#[derive(Error, Debug)]
10pub enum ConfigError {
11 #[error("Config parameter `{0}` not found.")]
12 NotFound(String),
13 #[error("Value for config parameter `{0}` is invalid: `{1:?}`. Expected: `{2:?}`")]
14 TypeError(String, AlgebraicValue, AlgebraicType),
15}
16
17#[derive(Error, Debug)]
19pub enum ErrorType {
20 #[error("Error Parsing `{value}` into type [{ty}]: {err}")]
21 Parse { value: String, ty: String, err: String },
22 #[error("Type Mismatch Join: `{lhs}` != `{rhs}`")]
23 TypeMismatchJoin { lhs: String, rhs: String },
24 #[error("Type Mismatch: `{lhs}` != `{rhs}`")]
25 TypeMismatch { lhs: String, rhs: String },
26 #[error("Type Mismatch: `{lhs}` {op} `{rhs}`, both sides must be an `{expected}` expression")]
27 TypeMismatchLogic {
28 op: OpLogic,
29 lhs: String,
30 rhs: String,
31 expected: String,
32 },
33}
34
35#[derive(Error, Debug)]
37pub enum ErrorVm {
38 #[error("TypeError {0}")]
39 Type(#[from] ErrorType),
40 #[error("ErrorLang {0}")]
41 Lang(#[from] ErrorLang),
42 #[error("RelationError {0}")]
43 Rel(#[from] RelationError),
44 #[error("AuthError {0}")]
45 Auth(#[from] AuthError),
46 #[error("Unsupported: {0}")]
47 Unsupported(String),
48 #[error("No source table with index {0:?}")]
49 NoSuchSource(SourceId),
50 #[error("ConfigError: {0}")]
51 Config(#[from] ConfigError),
52 #[error("{0}")]
53 Other(#[from] anyhow::Error),
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
57pub enum ErrorKind {
58 Custom(String),
59 Compiler,
60 TypeMismatch,
61 Db,
62 Query,
63 Duplicated,
64 Invalid,
65 NotFound,
66 Params,
67 OutOfBounds,
68 Timeout,
69 Unauthorized,
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
73pub struct ErrorCtx {
74 key: String,
75 value: String,
76}
77
78impl ErrorCtx {
79 pub fn new(key: &str, value: &str) -> Self {
80 Self {
81 key: key.into(),
82 value: value.into(),
83 }
84 }
85}
86
87#[derive(Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
89pub struct ErrorLang {
90 pub kind: ErrorKind,
91 pub msg: Option<String>,
92 pub context: Option<Vec<ErrorCtx>>,
94}
95
96impl ErrorLang {
97 pub fn new(kind: ErrorKind, msg: Option<&str>) -> Self {
98 Self {
99 kind,
100 msg: msg.map(|x| x.to_string()),
101 context: None,
102 }
103 }
104
105 pub fn with_ctx(self, of: ErrorCtx) -> Self {
106 let mut x = self;
107 if let Some(ref mut s) = x.context {
108 s.push(of)
109 } else {
110 x.context = Some(vec![of])
111 }
112 x
113 }
114}
115
116impl fmt::Display for ErrorLang {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "{:?}Error", self.kind)?;
119 if let Some(msg) = &self.msg {
120 writeln!(f, ": \"{}\"", msg)?;
121 }
122 if let Some(err) = self.context.as_deref() {
123 writeln!(f, " Context:")?;
124 for e in err {
125 writeln!(f, " {}: {}", e.key, e.value)?;
126 }
127 }
128 Ok(())
129 }
130}
131
132impl From<ErrorType> for ErrorLang {
133 fn from(x: ErrorType) -> Self {
134 ErrorLang::new(ErrorKind::TypeMismatch, Some(&x.to_string()))
135 }
136}
137
138impl From<ErrorVm> for ErrorLang {
139 fn from(err: ErrorVm) -> Self {
140 match err {
141 ErrorVm::Type(err) => err.into(),
142 ErrorVm::Other(err) => ErrorLang::new(ErrorKind::Db, Some(&err.to_string())),
143 ErrorVm::Rel(err) => ErrorLang::new(ErrorKind::Db, Some(&err.to_string())),
144 ErrorVm::Unsupported(err) => ErrorLang::new(ErrorKind::Compiler, Some(&err)),
145 ErrorVm::Lang(err) => err,
146 ErrorVm::Auth(err) => ErrorLang::new(ErrorKind::Unauthorized, Some(&err.to_string())),
147 ErrorVm::Config(err) => ErrorLang::new(ErrorKind::Db, Some(&err.to_string())),
148 err @ ErrorVm::NoSuchSource(_) => ErrorLang {
149 kind: ErrorKind::Invalid,
150 msg: Some(format!("{err:?}")),
151 context: None,
152 },
153 }
154 }
155}
156
157impl From<RelationError> for ErrorLang {
158 fn from(err: RelationError) -> Self {
159 ErrorVm::Rel(err).into()
160 }
161}