mirror of
https://github.com/chatmail/core.git
synced 2026-05-15 12:56:30 +03:00
Add API versioning to the JSON-RPC API
This commit is contained in:
@@ -4453,17 +4453,29 @@ mod jsonrpc {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn dc_jsonrpc_init(
|
pub unsafe extern "C" fn dc_jsonrpc_init(
|
||||||
account_manager: *mut dc_accounts_t,
|
account_manager: *mut dc_accounts_t,
|
||||||
|
api_version: *const libc::c_char,
|
||||||
) -> *mut dc_jsonrpc_instance_t {
|
) -> *mut dc_jsonrpc_instance_t {
|
||||||
if account_manager.is_null() {
|
if account_manager.is_null() {
|
||||||
eprintln!("ignoring careless call to dc_jsonrpc_init()");
|
eprintln!("ignoring careless call to dc_jsonrpc_init()");
|
||||||
return ptr::null_mut();
|
return ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
let api_version = to_string_lossy(api_version);
|
||||||
|
|
||||||
let cmd_api =
|
let rpc_api = match &api_version {
|
||||||
deltachat_jsonrpc::api::CommandApi::from_arc((*account_manager).inner.clone());
|
"v0" => {
|
||||||
|
deltachat_jsonrpc::api::DeltaChatApiV0::from_arc((*account_manager).inner.clone())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
error!(
|
||||||
|
ctx,
|
||||||
|
"The requested JSON-RPC API version is not supported.", err
|
||||||
|
);
|
||||||
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (request_handle, receiver) = RpcClient::new();
|
let (request_handle, receiver) = RpcClient::new();
|
||||||
let handle = RpcSession::new(request_handle, cmd_api);
|
let handle = RpcSession::new(request_handle, rpc_api);
|
||||||
|
|
||||||
let instance = dc_jsonrpc_instance_t { receiver, handle };
|
let instance = dc_jsonrpc_instance_t { receiver, handle };
|
||||||
|
|
||||||
|
|||||||
@@ -34,20 +34,20 @@ use types::webxdc::WebxdcMessageInfo;
|
|||||||
use self::types::message::MessageViewtype;
|
use self::types::message::MessageViewtype;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CommandApi {
|
pub struct DeltaChatApiV0 {
|
||||||
pub(crate) accounts: Arc<RwLock<Accounts>>,
|
pub(crate) accounts: Arc<RwLock<Accounts>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandApi {
|
impl DeltaChatApiV0 {
|
||||||
pub fn new(accounts: Accounts) -> Self {
|
pub fn new(accounts: Accounts) -> Self {
|
||||||
CommandApi {
|
DeltaChatApiV0 {
|
||||||
accounts: Arc::new(RwLock::new(accounts)),
|
accounts: Arc::new(RwLock::new(accounts)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn from_arc(accounts: Arc<RwLock<Accounts>>) -> Self {
|
pub fn from_arc(accounts: Arc<RwLock<Accounts>>) -> Self {
|
||||||
CommandApi { accounts }
|
DeltaChatApiV0 { accounts }
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_context(&self, id: u32) -> Result<deltachat::context::Context> {
|
async fn get_context(&self, id: u32) -> Result<deltachat::context::Context> {
|
||||||
@@ -63,7 +63,7 @@ impl CommandApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rpc(all_positional, ts_outdir = "typescript/generated")]
|
#[rpc(all_positional, ts_outdir = "typescript/generated")]
|
||||||
impl CommandApi {
|
impl DeltaChatApiV0 {
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
// Misc top level functions
|
// Misc top level functions
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ pub enum Account {
|
|||||||
color: String,
|
color: String,
|
||||||
},
|
},
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
Unconfigured {
|
Unconfigured { id: u32 },
|
||||||
id: u32,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
pub use api::events;
|
pub use api::events;
|
||||||
|
pub use api::{Accounts, DeltaChatApiV0};
|
||||||
pub use yerpc;
|
pub use yerpc;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::api::{Accounts, CommandApi};
|
use super::api::{Accounts, DeltaChatApiV0};
|
||||||
use async_channel::unbounded;
|
use async_channel::unbounded;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use yerpc::{RpcClient, RpcSession};
|
|||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
use api::events::event_to_json_rpc_notification;
|
use api::events::event_to_json_rpc_notification;
|
||||||
use api::{Accounts, CommandApi};
|
use api::{Accounts, DeltaChatApiV0};
|
||||||
|
|
||||||
const DEFAULT_PORT: u16 = 20808;
|
const DEFAULT_PORT: u16 = 20808;
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@ async fn main() -> Result<(), std::io::Error> {
|
|||||||
.unwrap_or(DEFAULT_PORT);
|
.unwrap_or(DEFAULT_PORT);
|
||||||
log::info!("Starting with accounts directory `{path}`.");
|
log::info!("Starting with accounts directory `{path}`.");
|
||||||
let accounts = Accounts::new(PathBuf::from(&path)).await.unwrap();
|
let accounts = Accounts::new(PathBuf::from(&path)).await.unwrap();
|
||||||
let state = CommandApi::new(accounts);
|
let state = DeltaChatApiV0::new(accounts);
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/ws", get(handler))
|
.route("/rpc/v0", get(handler))
|
||||||
.layer(Extension(state.clone()));
|
.layer(Extension(state.clone()));
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export class AccountManager extends EventEmitter {
|
|||||||
debug('Started event handler')
|
debug('Started event handler')
|
||||||
}
|
}
|
||||||
|
|
||||||
startJsonRpcHandler(callback: ((response: string) => void) | null) {
|
startJsonRpcHandler(callback: ((response: string) => void) | null, apiVersion: string = "v0") {
|
||||||
if (this.dcn_accounts === null) {
|
if (this.dcn_accounts === null) {
|
||||||
throw new Error('dcn_account is null')
|
throw new Error('dcn_account is null')
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ export class AccountManager extends EventEmitter {
|
|||||||
throw new Error('jsonrpc was started already')
|
throw new Error('jsonrpc was started already')
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.dcn_accounts_start_jsonrpc(this.dcn_accounts, callback.bind(this))
|
binding.dcn_accounts_start_jsonrpc(this.dcn_accounts, apiVersion, callback.bind(this))
|
||||||
debug('Started JSON-RPC handler')
|
debug('Started JSON-RPC handler')
|
||||||
this.jsonRpcStarted = true
|
this.jsonRpcStarted = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3313,9 +3313,10 @@ static void call_accounts_js_jsonrpc_handler(napi_env env, napi_value js_callbac
|
|||||||
}
|
}
|
||||||
|
|
||||||
NAPI_METHOD(dcn_accounts_start_jsonrpc) {
|
NAPI_METHOD(dcn_accounts_start_jsonrpc) {
|
||||||
NAPI_ARGV(2);
|
NAPI_ARGV(3);
|
||||||
NAPI_DCN_ACCOUNTS();
|
NAPI_DCN_ACCOUNTS();
|
||||||
napi_value callback = argv[1];
|
NAPI_ARGV_UTF8_MALLOC(api_version, 1);
|
||||||
|
napi_value callback = argv[2];
|
||||||
|
|
||||||
TRACE("calling..");
|
TRACE("calling..");
|
||||||
napi_value async_resource_name;
|
napi_value async_resource_name;
|
||||||
@@ -3338,7 +3339,7 @@ NAPI_METHOD(dcn_accounts_start_jsonrpc) {
|
|||||||
TRACE("done");
|
TRACE("done");
|
||||||
|
|
||||||
dcn_accounts->gc = 0;
|
dcn_accounts->gc = 0;
|
||||||
dcn_accounts->jsonrpc_instance = dc_jsonrpc_init(dcn_accounts->dc_accounts);
|
dcn_accounts->jsonrpc_instance = dc_jsonrpc_init(dcn_accounts->dc_accounts, api_version);
|
||||||
|
|
||||||
TRACE("creating uv thread..");
|
TRACE("creating uv thread..");
|
||||||
uv_thread_create(&dcn_accounts->jsonrpc_thread, accounts_jsonrpc_thread_func, dcn_accounts);
|
uv_thread_create(&dcn_accounts->jsonrpc_thread, accounts_jsonrpc_thread_func, dcn_accounts);
|
||||||
|
|||||||
Reference in New Issue
Block a user