-
Notifications
You must be signed in to change notification settings - Fork 212
/
rpc.rs
66 lines (60 loc) 路 3.21 KB
/
rpc.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
use crate::{json_rpc::method_names::*, CoreError, CoreResult, GenericApi};
use jsonrpc_core::{types::error::Error as JsonRpcError, IoHandler, Params};
use std::sync::Arc;
/// Initialize a JSON-RPC ready migration engine API.
pub fn rpc_api(prisma_schema: Option<String>, host: Arc<dyn migration_connector::ConnectorHost>) -> IoHandler {
let mut io_handler = IoHandler::default();
let api = Arc::new(crate::state::EngineState::new(prisma_schema, Some(host)));
for cmd in METHOD_NAMES {
let api = api.clone();
io_handler.add_method(cmd, move |params: Params| {
Box::pin(run_command(api.clone(), cmd, params))
});
}
io_handler
}
#[allow(clippy::redundant_allocation)]
async fn run_command(
executor: Arc<dyn GenericApi>,
cmd: &str,
params: Params,
) -> Result<serde_json::Value, JsonRpcError> {
tracing::debug!(?cmd, "running the command");
match cmd {
APPLY_MIGRATIONS => render(executor.apply_migrations(params.parse()?).await),
CREATE_DATABASE => render(executor.create_database(params.parse()?).await),
CREATE_MIGRATION => render(executor.create_migration(params.parse()?).await),
DB_EXECUTE => render(executor.db_execute(params.parse()?).await),
DEV_DIAGNOSTIC => render(executor.dev_diagnostic(params.parse()?).await),
DIFF => render(executor.diff(params.parse()?).await),
DEBUG_PANIC => render(executor.debug_panic().await),
DIAGNOSE_MIGRATION_HISTORY => render(executor.diagnose_migration_history(params.parse()?).await),
ENSURE_CONNECTION_VALIDITY => render(executor.ensure_connection_validity(params.parse()?).await),
EVALUATE_DATA_LOSS => render(executor.evaluate_data_loss(params.parse()?).await),
GET_DATABASE_VERSION => render(executor.version().await),
INTROSPECT => render(executor.introspect(params.parse()?).await),
LIST_MIGRATION_DIRECTORIES => render(executor.list_migration_directories(params.parse()?).await),
MARK_MIGRATION_APPLIED => render(executor.mark_migration_applied(params.parse()?).await),
MARK_MIGRATION_ROLLED_BACK => render(executor.mark_migration_rolled_back(params.parse()?).await),
// TODO(MultiSchema): we probably need to grab the namespaces from the params
RESET => render(executor.reset().await),
SCHEMA_PUSH => render(executor.schema_push(params.parse()?).await),
other => unreachable!("Unknown command {}", other),
}
}
fn render(result: CoreResult<impl serde::Serialize>) -> jsonrpc_core::Result<jsonrpc_core::Value> {
result
.map(|response| serde_json::to_value(response).expect("Rendering of RPC response failed"))
.map_err(render_jsonrpc_error)
}
fn render_jsonrpc_error(crate_error: CoreError) -> JsonRpcError {
serde_json::to_value(&crate_error.to_user_facing())
.map(|data| JsonRpcError {
// We separate the JSON-RPC error code (defined by the JSON-RPC spec) from the
// prisma error code, which is located in `data`.
code: jsonrpc_core::types::error::ErrorCode::ServerError(4466),
message: "An error happened. Check the data field for details.".to_string(),
data: Some(data),
})
.unwrap()
}