1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Deserialize)]
5pub struct Request {
6 pub id: Value,
7 pub method: String,
8 #[serde(default)]
9 pub params: Value,
10}
11
12#[derive(Debug, Serialize)]
13pub struct Response {
14 id: Value,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 result: Option<Value>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 error: Option<ErrorBody>,
19}
20
21impl Response {
22 pub fn ok(id: Value, result: Value) -> Self {
23 Self {
24 id,
25 result: Some(result),
26 error: None,
27 }
28 }
29
30 pub fn err(id: Value, error: ServerError) -> Self {
31 Self {
32 id,
33 result: None,
34 error: Some(ErrorBody {
35 code: error.code,
36 message: error.message,
37 }),
38 }
39 }
40}
41
42#[derive(Debug, Serialize)]
43struct ErrorBody {
44 code: ErrorCode,
45 message: String,
46}
47
48#[derive(Debug, Clone, Copy, Serialize)]
49pub enum ErrorCode {
50 ElementNotFound,
51 ElementNotVisible,
52 Timeout,
53 RetryExhausted,
54 Cdp,
55 InvalidPage,
56 InvalidParams,
57 UnknownMethod,
58 Internal,
59}
60
61#[derive(Debug)]
62pub struct ServerError {
63 pub code: ErrorCode,
64 pub message: String,
65}
66
67impl ServerError {
68 pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
69 Self {
70 code,
71 message: message.into(),
72 }
73 }
74
75 pub fn invalid_params(message: impl Into<String>) -> Self {
76 Self::new(ErrorCode::InvalidParams, message)
77 }
78
79 pub fn invalid_page(page_id: &str) -> Self {
80 Self::new(
81 ErrorCode::InvalidPage,
82 format!("unknown pageId \"{page_id}\""),
83 )
84 }
85
86 pub fn unknown_method(method: &str) -> Self {
87 Self::new(
88 ErrorCode::UnknownMethod,
89 format!("unknown method \"{method}\""),
90 )
91 }
92
93 pub fn internal(message: impl Into<String>) -> Self {
94 Self::new(ErrorCode::Internal, message)
95 }
96}
97
98impl From<eoka::Error> for ServerError {
99 fn from(err: eoka::Error) -> Self {
100 let code = match &err {
101 eoka::Error::ElementNotFound(_) => ErrorCode::ElementNotFound,
102 eoka::Error::ElementNotVisible { .. } => ErrorCode::ElementNotVisible,
103 eoka::Error::Timeout(_) => ErrorCode::Timeout,
104 eoka::Error::RetryExhausted { .. } => ErrorCode::RetryExhausted,
105 eoka::Error::Cdp { .. } => ErrorCode::Cdp,
106 _ => ErrorCode::Internal,
107 };
108 Self {
109 code,
110 message: err.to_string(),
111 }
112 }
113}