2022-07-04 01:03:26 +00:00
|
|
|
use serde::Serialize;
|
2023-07-01 19:09:15 +00:00
|
|
|
use serde_json::{json, Value as Json};
|
2022-07-04 01:03:26 +00:00
|
|
|
use std::borrow::Cow;
|
2022-07-07 10:25:22 +00:00
|
|
|
use surrealdb::channel::Sender;
|
2023-07-01 19:09:15 +00:00
|
|
|
use surrealdb::dbs;
|
|
|
|
use surrealdb::dbs::Notification;
|
2023-04-29 15:58:22 +00:00
|
|
|
use surrealdb::sql;
|
2022-07-04 01:03:26 +00:00
|
|
|
use surrealdb::sql::Value;
|
2023-07-01 19:09:15 +00:00
|
|
|
use tracing::instrument;
|
2022-07-07 10:25:22 +00:00
|
|
|
use warp::ws::Message;
|
2022-07-04 01:03:26 +00:00
|
|
|
|
2022-10-25 13:19:44 +00:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub enum Output {
|
|
|
|
Json, // JSON
|
|
|
|
Cbor, // CBOR
|
2023-03-27 12:52:28 +00:00
|
|
|
Pack, // MessagePack
|
2022-10-25 13:19:44 +00:00
|
|
|
Full, // Full type serialization
|
2022-07-04 01:03:26 +00:00
|
|
|
}
|
|
|
|
|
2023-07-01 19:09:15 +00:00
|
|
|
/// The data returned by the database
|
|
|
|
// The variants here should be in exactly the same order as `surrealdb::engine::remote::ws::Data`
|
|
|
|
// In future, they will possibly be merged to avoid having to keep them in sync.
|
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub enum Data {
|
|
|
|
/// Generally methods return a `sql::Value`
|
|
|
|
Other(Value),
|
|
|
|
/// The query methods, `query` and `query_with` return a `Vec` of responses
|
|
|
|
Query(Vec<dbs::Response>),
|
|
|
|
/// Live queries return a notification
|
|
|
|
Live(Notification),
|
|
|
|
// Add new variants here
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Value> for Data {
|
|
|
|
fn from(v: Value) -> Self {
|
|
|
|
Data::Other(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Vec<dbs::Response>> for Data {
|
|
|
|
fn from(v: Vec<dbs::Response>) -> Self {
|
|
|
|
Data::Query(v)
|
|
|
|
}
|
2022-07-04 01:03:26 +00:00
|
|
|
}
|
|
|
|
|
2023-07-01 19:09:15 +00:00
|
|
|
impl From<Notification> for Data {
|
|
|
|
fn from(n: Notification) -> Self {
|
|
|
|
Data::Live(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct Response {
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
|
|
id: Option<Value>,
|
|
|
|
result: Result<Data, Failure>,
|
2022-10-25 13:19:44 +00:00
|
|
|
}
|
|
|
|
|
2023-07-01 19:09:15 +00:00
|
|
|
impl Response {
|
2023-05-05 18:54:49 +00:00
|
|
|
/// Convert and simplify the value into JSON
|
2023-05-02 11:17:27 +00:00
|
|
|
#[inline]
|
2023-05-05 18:54:49 +00:00
|
|
|
fn simplify(self) -> Json {
|
2023-07-01 19:09:15 +00:00
|
|
|
let mut value = match self.result {
|
|
|
|
Ok(data) => {
|
|
|
|
let value = match data {
|
|
|
|
Data::Query(vec) => sql::to_value(vec).unwrap(),
|
|
|
|
Data::Live(nofication) => sql::to_value(nofication).unwrap(),
|
|
|
|
Data::Other(value) => value,
|
|
|
|
};
|
|
|
|
json!({
|
|
|
|
"result": Json::from(value),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
Err(failure) => json!({
|
|
|
|
"error": failure,
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
if let Some(id) = self.id {
|
|
|
|
value["id"] = id.into();
|
|
|
|
}
|
|
|
|
value
|
2023-04-29 15:58:22 +00:00
|
|
|
}
|
2023-07-01 19:09:15 +00:00
|
|
|
|
2023-05-05 18:54:49 +00:00
|
|
|
/// Send the response to the WebSocket channel
|
2023-07-01 19:09:15 +00:00
|
|
|
#[instrument(skip_all, name = "rpc response", fields(response = ?self))]
|
2022-10-25 13:19:44 +00:00
|
|
|
pub async fn send(self, out: Output, chn: Sender<Message>) {
|
2023-07-01 19:09:15 +00:00
|
|
|
let message = match out {
|
2022-10-25 13:19:44 +00:00
|
|
|
Output::Json => {
|
2023-05-05 18:54:49 +00:00
|
|
|
let res = serde_json::to_string(&self.simplify()).unwrap();
|
2023-07-01 19:09:15 +00:00
|
|
|
Message::text(res)
|
2022-10-25 13:19:44 +00:00
|
|
|
}
|
|
|
|
Output::Cbor => {
|
2023-05-05 18:54:49 +00:00
|
|
|
let res = serde_cbor::to_vec(&self.simplify()).unwrap();
|
2023-07-01 19:09:15 +00:00
|
|
|
Message::binary(res)
|
2022-10-25 13:19:44 +00:00
|
|
|
}
|
|
|
|
Output::Pack => {
|
2023-05-05 18:54:49 +00:00
|
|
|
let res = serde_pack::to_vec(&self.simplify()).unwrap();
|
2023-07-01 19:09:15 +00:00
|
|
|
Message::binary(res)
|
2022-10-25 13:19:44 +00:00
|
|
|
}
|
2022-10-25 13:38:23 +00:00
|
|
|
Output::Full => {
|
2023-07-01 19:09:15 +00:00
|
|
|
let res = surrealdb::sql::serde::serialize(&self).unwrap();
|
|
|
|
Message::binary(res)
|
2022-10-25 13:38:23 +00:00
|
|
|
}
|
2023-07-01 19:09:15 +00:00
|
|
|
};
|
|
|
|
let _ = chn.send(message).await;
|
2023-07-04 21:02:10 +00:00
|
|
|
trace!("Response sent");
|
2022-07-07 10:25:22 +00:00
|
|
|
}
|
2022-07-04 01:03:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize)]
|
|
|
|
pub struct Failure {
|
|
|
|
code: i64,
|
|
|
|
message: Cow<'static, str>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Failure {
|
|
|
|
pub const PARSE_ERROR: Failure = Failure {
|
|
|
|
code: -32700,
|
|
|
|
message: Cow::Borrowed("Parse error"),
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const INVALID_REQUEST: Failure = Failure {
|
|
|
|
code: -32600,
|
|
|
|
message: Cow::Borrowed("Invalid Request"),
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const METHOD_NOT_FOUND: Failure = Failure {
|
|
|
|
code: -32601,
|
|
|
|
message: Cow::Borrowed("Method not found"),
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const INVALID_PARAMS: Failure = Failure {
|
|
|
|
code: -32602,
|
|
|
|
message: Cow::Borrowed("Invalid params"),
|
|
|
|
};
|
|
|
|
|
|
|
|
pub const INTERNAL_ERROR: Failure = Failure {
|
|
|
|
code: -32603,
|
|
|
|
message: Cow::Borrowed("Internal error"),
|
|
|
|
};
|
|
|
|
|
|
|
|
pub fn custom<S>(message: S) -> Failure
|
|
|
|
where
|
|
|
|
Cow<'static, str>: From<S>,
|
|
|
|
{
|
|
|
|
Failure {
|
|
|
|
code: -32000,
|
|
|
|
message: message.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-10-19 22:54:41 +00:00
|
|
|
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Create a JSON RPC result response
|
2023-07-01 19:09:15 +00:00
|
|
|
pub fn success<T: Into<Data>>(id: Option<Value>, data: T) -> Response {
|
2022-10-19 22:54:41 +00:00
|
|
|
Response {
|
|
|
|
id,
|
2023-07-01 19:09:15 +00:00
|
|
|
result: Ok(data.into()),
|
2022-10-19 22:54:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-23 09:42:59 +00:00
|
|
|
/// Create a JSON RPC failure response
|
2023-07-01 19:09:15 +00:00
|
|
|
pub fn failure(id: Option<Value>, err: Failure) -> Response {
|
2022-10-19 22:54:41 +00:00
|
|
|
Response {
|
|
|
|
id,
|
2023-07-01 19:09:15 +00:00
|
|
|
result: Err(err),
|
2022-10-19 22:54:41 +00:00
|
|
|
}
|
|
|
|
}
|