/
endpoints.rs
124 lines (112 loc) · 2.95 KB
/
endpoints.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use crate::{
hooks::{InvokeError, InvokeMessage, InvokeResolver},
Config, Invoke, PackageInfo, Runtime, Window,
};
pub use anyhow::Result;
use serde::{Deserialize, Serialize};
use serde_json::Value as JsonValue;
use std::sync::Arc;
mod event;
mod window;
/// The context passed to the invoke handler.
pub struct InvokeContext<R: Runtime> {
pub window: Window<R>,
pub config: Arc<Config>,
pub package_info: PackageInfo,
}
#[cfg(test)]
impl<R: Runtime> Clone for InvokeContext<R> {
fn clone(&self) -> Self {
Self {
window: self.window.clone(),
config: self.config.clone(),
package_info: self.package_info.clone(),
}
}
}
/// The response for a JS `invoke` call.
pub struct InvokeResponse {
json: Result<JsonValue>,
}
impl<T: Serialize> From<T> for InvokeResponse {
fn from(value: T) -> Self {
Self {
json: serde_json::to_value(value).map_err(Into::into),
}
}
}
#[derive(Deserialize)]
#[serde(tag = "module", content = "message")]
enum Module {
Window(Box<window::Cmd>),
Event(event::Cmd),
}
impl Module {
fn run<R: Runtime>(
self,
window: Window<R>,
resolver: InvokeResolver<R>,
config: Arc<Config>,
package_info: PackageInfo,
) {
let context = InvokeContext {
window,
config,
package_info,
};
match self {
Self::Window(cmd) => resolver.respond_async(async move {
cmd
.run(context)
.await
.and_then(|r| r.json)
.map_err(InvokeError::from_anyhow)
}),
Self::Event(cmd) => resolver.respond_async(async move {
cmd
.run(context)
.and_then(|r| r.json)
.map_err(InvokeError::from_anyhow)
}),
}
}
}
pub(crate) fn handle<R: Runtime>(
module: String,
invoke: Invoke<R>,
config: Arc<Config>,
package_info: &PackageInfo,
) {
let Invoke { message, resolver } = invoke;
let InvokeMessage {
mut payload,
window,
..
} = message;
if let JsonValue::Object(ref mut obj) = payload {
obj.insert("module".to_string(), JsonValue::String(module.clone()));
}
match serde_json::from_value::<Module>(payload) {
Ok(module) => module.run(window, resolver, config, package_info.clone()),
Err(e) => {
let message = e.to_string();
if message.starts_with("unknown variant") {
let mut s = message.split('`');
s.next();
if let Some(unknown_variant_name) = s.next() {
if unknown_variant_name == module {
return resolver.reject(format!(
"The `{module}` module is not enabled. You must enable one of its APIs in the allowlist.",
));
} else if module == "Window" {
return resolver.reject(window::into_allowlist_error(unknown_variant_name).to_string());
}
}
}
resolver.reject(message);
}
}
}