feat(jsonrpc): generate OpenRPC definitions

When running `cargo test` in the deltachat-jsonrpc folder,
a new file `openrpc/openrpc.json` will be created with an
[OpenRPC](https://spec.open-rpc.org/) definition.

It can be copy-pasted into the
[OpenRPC playground](https://playground.open-rpc.org/)
and used to generate clients in other languages.
This commit is contained in:
Franz Heinzmann (Frando)
2022-11-25 15:24:25 +01:00
committed by link2xt
parent b9b0d20e8d
commit 5b435d11c7
17 changed files with 88 additions and 38 deletions

51
Cargo.lock generated
View File

@@ -1242,6 +1242,7 @@ dependencies = [
"log", "log",
"num-traits", "num-traits",
"sanitize-filename", "sanitize-filename",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"tempfile", "tempfile",
@@ -1514,6 +1515,12 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "dyn-clone"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
[[package]] [[package]]
name = "ecdsa" name = "ecdsa"
version = "0.14.8" version = "0.14.8"
@@ -4248,6 +4255,30 @@ dependencies = [
"windows-sys 0.42.0", "windows-sys 0.42.0",
] ]
[[package]]
name = "schemars"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f"
dependencies = [
"dyn-clone",
"schemars_derive",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "109da1e6b197438deb6db99952990c7f959572794b80ff93707d55a232545e7c"
dependencies = [
"proc-macro2",
"quote",
"serde_derive_internals",
"syn 1.0.109",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@@ -4368,6 +4399,17 @@ dependencies = [
"syn 2.0.15", "syn 2.0.15",
] ]
[[package]]
name = "serde_derive_internals"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.96" version = "1.0.96"
@@ -5799,9 +5841,9 @@ dependencies = [
[[package]] [[package]]
name = "yerpc" name = "yerpc"
version = "0.4.4" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2c26a804eaa30c1ff1a296dc6dd1a7d7c622750dafcd0d6b2ed5e3c5c3beb22" checksum = "30fc983d32883ecb563227a2dcdcbe8567decd9c533b5ecca7e3099e2f7d4c96"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-channel", "async-channel",
@@ -5811,6 +5853,7 @@ dependencies = [
"futures", "futures",
"futures-util", "futures-util",
"log", "log",
"schemars",
"serde", "serde",
"serde_json", "serde_json",
"tokio", "tokio",
@@ -5821,9 +5864,9 @@ dependencies = [
[[package]] [[package]]
name = "yerpc_derive" name = "yerpc_derive"
version = "0.4.3" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bd53ff9053698697b92c2535bf7ecb983fd5d546d690b7c725e5070d6d9a620" checksum = "6d6b8ce490e8719fe84d7d80ad4d58572b2ea9d7a83d156f6afd6ab3ad5cfb94"
dependencies = [ dependencies = [
"convert_case 0.5.0", "convert_case 0.5.0",
"darling 0.14.3", "darling 0.14.3",

View File

@@ -25,7 +25,7 @@ anyhow = "1"
thiserror = "1" thiserror = "1"
rand = "0.8" rand = "0.8"
once_cell = "1.17.0" once_cell = "1.17.0"
yerpc = { version = "0.4.4", features = ["anyhow_expose"] } yerpc = { version = "0.5.1", features = ["anyhow_expose"] }
[features] [features]
default = ["vendored"] default = ["vendored"]

View File

@@ -15,13 +15,14 @@ required-features = ["webserver"]
anyhow = "1" anyhow = "1"
deltachat = { path = ".." } deltachat = { path = ".." }
num-traits = "0.2" num-traits = "0.2"
schemars = "0.8.11"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tempfile = "3.3.0" tempfile = "3.3.0"
log = "0.4" log = "0.4"
async-channel = { version = "1.8.0" } async-channel = { version = "1.8.0" }
futures = { version = "0.3.28" } futures = { version = "0.3.28" }
serde_json = "1.0.96" serde_json = "1.0.96"
yerpc = { version = "0.4.4", features = ["anyhow_expose"] } yerpc = { version = "0.5.1", features = ["anyhow_expose", "openrpc"] }
typescript-type-def = { version = "0.5.5", features = ["json_value"] } typescript-type-def = { version = "0.5.5", features = ["json_value"] }
tokio = { version = "1.28.0" } tokio = { version = "1.28.0" }
sanitize-filename = "0.4" sanitize-filename = "0.4"

View File

@@ -144,7 +144,11 @@ impl CommandApi {
} }
} }
#[rpc(all_positional, ts_outdir = "typescript/generated")] #[rpc(
all_positional,
ts_outdir = "typescript/generated",
openrpc_outdir = "openrpc"
)]
impl CommandApi { impl CommandApi {
/// Test function. /// Test function.
async fn sleep(&self, delay: f64) { async fn sleep(&self, delay: f64) {

View File

@@ -6,7 +6,7 @@ use typescript_type_def::TypeDef;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum Account { pub enum Account {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View File

@@ -13,7 +13,7 @@ use typescript_type_def::TypeDef;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
use super::contact::ContactObject; use super::contact::ContactObject;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct FullChat { pub struct FullChat {
id: u32, id: u32,
@@ -121,7 +121,7 @@ impl FullChat {
/// - can_send /// - can_send
/// ///
/// used when you only need the basic metadata of a chat like type, name, profile picture /// used when you only need the basic metadata of a chat like type, name, profile picture
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct BasicChat { pub struct BasicChat {
id: u32, id: u32,
@@ -166,7 +166,7 @@ impl BasicChat {
} }
} }
#[derive(Clone, Serialize, Deserialize, TypeDef)] #[derive(Clone, Serialize, Deserialize, TypeDef, schemars::JsonSchema)]
pub enum MuteDuration { pub enum MuteDuration {
NotMuted, NotMuted,
Forever, Forever,
@@ -191,7 +191,7 @@ impl MuteDuration {
} }
} }
#[derive(Clone, Serialize, Deserialize, TypeDef)] #[derive(Clone, Serialize, Deserialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "ChatVisibility")] #[serde(rename = "ChatVisibility")]
pub enum JSONRPCChatVisibility { pub enum JSONRPCChatVisibility {
Normal, Normal,

View File

@@ -8,13 +8,16 @@ use deltachat::{
chatlist::Chatlist, chatlist::Chatlist,
}; };
use num_traits::cast::ToPrimitive; use num_traits::cast::ToPrimitive;
use serde::Serialize; use serde::{Deserialize, Serialize};
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
use super::message::MessageViewtype; use super::message::MessageViewtype;
#[derive(Serialize, TypeDef)] #[derive(Deserialize, Serialize, TypeDef, schemars::JsonSchema)]
pub struct ChatListEntry(pub u32, pub u32);
#[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum ChatListItemFetchResult { pub enum ChatListItemFetchResult {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]

View File

@@ -6,7 +6,7 @@ use typescript_type_def::TypeDef;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Contact", rename_all = "camelCase")] #[serde(rename = "Contact", rename_all = "camelCase")]
pub struct ContactObject { pub struct ContactObject {
address: String, address: String,

View File

@@ -2,7 +2,7 @@ use deltachat::{Event as CoreEvent, EventType as CoreEventType};
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct Event { pub struct Event {
/// Event payload. /// Event payload.
@@ -21,7 +21,7 @@ impl From<CoreEvent> for Event {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum EventType { pub enum EventType {
/// The library-user may write an informational string to the log. /// The library-user may write an informational string to the log.

View File

@@ -2,7 +2,7 @@ use deltachat::net::HttpResponse as CoreHttpResponse;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
pub struct HttpResponse { pub struct HttpResponse {
/// base64-encoded response body. /// base64-encoded response body.
blob: String, blob: String,

View File

@@ -2,7 +2,7 @@ use deltachat::location::Location;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Location", rename_all = "camelCase")] #[serde(rename = "Location", rename_all = "camelCase")]
pub struct JsonrpcLocation { pub struct JsonrpcLocation {
pub location_id: u32, pub location_id: u32,

View File

@@ -10,8 +10,7 @@ use deltachat::message::MsgId;
use deltachat::message::Viewtype; use deltachat::message::Viewtype;
use deltachat::reaction::get_msg_reactions; use deltachat::reaction::get_msg_reactions;
use num_traits::cast::ToPrimitive; use num_traits::cast::ToPrimitive;
use serde::Deserialize; use serde::{Deserialize, Serialize};
use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
use super::color_int_to_hex_string; use super::color_int_to_hex_string;
@@ -19,14 +18,14 @@ use super::contact::ContactObject;
use super::reactions::JSONRPCReactions; use super::reactions::JSONRPCReactions;
use super::webxdc::WebxdcMessageInfo; use super::webxdc::WebxdcMessageInfo;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", tag = "variant")] #[serde(rename_all = "camelCase", tag = "variant")]
pub enum MessageLoadResult { pub enum MessageLoadResult {
Message(MessageObject), Message(MessageObject),
LoadingError { error: String }, LoadingError { error: String },
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Message", rename_all = "camelCase")] #[serde(rename = "Message", rename_all = "camelCase")]
pub struct MessageObject { pub struct MessageObject {
id: u32, id: u32,
@@ -86,7 +85,7 @@ pub struct MessageObject {
reactions: Option<JSONRPCReactions>, reactions: Option<JSONRPCReactions>,
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(tag = "kind")] #[serde(tag = "kind")]
enum MessageQuote { enum MessageQuote {
JustText { JustText {
@@ -238,7 +237,7 @@ impl MessageObject {
} }
} }
#[derive(Serialize, Deserialize, TypeDef)] #[derive(Serialize, Deserialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Viewtype")] #[serde(rename = "Viewtype")]
pub enum MessageViewtype { pub enum MessageViewtype {
Unknown, Unknown,
@@ -314,7 +313,7 @@ impl From<MessageViewtype> for Viewtype {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
pub enum DownloadState { pub enum DownloadState {
Done, Done,
Available, Available,
@@ -333,7 +332,7 @@ impl From<download::DownloadState> for DownloadState {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
pub enum SystemMessageType { pub enum SystemMessageType {
Unknown, Unknown,
GroupNameChanged, GroupNameChanged,
@@ -388,7 +387,7 @@ impl From<deltachat::mimeparser::SystemMessage> for SystemMessageType {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MessageNotificationInfo { pub struct MessageNotificationInfo {
id: u32, id: u32,
@@ -446,7 +445,7 @@ impl MessageNotificationInfo {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MessageSearchResult { pub struct MessageSearchResult {
id: u32, id: u32,
@@ -507,7 +506,7 @@ impl MessageSearchResult {
} }
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase", rename = "MessageListItem", tag = "kind")] #[serde(rename_all = "camelCase", rename = "MessageListItem", tag = "kind")]
pub enum JSONRPCMessageListItem { pub enum JSONRPCMessageListItem {
Message { Message {
@@ -533,7 +532,7 @@ impl From<ChatItem> for JSONRPCMessageListItem {
} }
} }
#[derive(Deserialize, TypeDef)] #[derive(Deserialize, Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MessageData { pub struct MessageData {
pub text: Option<String>, pub text: Option<String>,
@@ -545,7 +544,7 @@ pub struct MessageData {
pub quoted_message_id: Option<u32>, pub quoted_message_id: Option<u32>,
} }
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct MessageReadReceipt { pub struct MessageReadReceipt {
pub contact_id: u32, pub contact_id: u32,

View File

@@ -3,7 +3,7 @@ use num_traits::cast::ToPrimitive;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct ProviderInfo { pub struct ProviderInfo {
pub before_login_hint: String, pub before_login_hint: String,

View File

@@ -2,7 +2,7 @@ use deltachat::qr::Qr;
use serde::Serialize; use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Qr", rename_all = "camelCase")] #[serde(rename = "Qr", rename_all = "camelCase")]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum QrObject { pub enum QrObject {

View File

@@ -6,7 +6,7 @@ use serde::Serialize;
use typescript_type_def::TypeDef; use typescript_type_def::TypeDef;
/// A single reaction emoji. /// A single reaction emoji.
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Reaction", rename_all = "camelCase")] #[serde(rename = "Reaction", rename_all = "camelCase")]
pub struct JSONRPCReaction { pub struct JSONRPCReaction {
/// Emoji. /// Emoji.
@@ -20,7 +20,7 @@ pub struct JSONRPCReaction {
} }
/// Structure representing all reactions to a particular message. /// Structure representing all reactions to a particular message.
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "Reactions", rename_all = "camelCase")] #[serde(rename = "Reactions", rename_all = "camelCase")]
pub struct JSONRPCReactions { pub struct JSONRPCReactions {
/// Map from a contact to it's reaction to message. /// Map from a contact to it's reaction to message.

View File

@@ -8,7 +8,7 @@ use typescript_type_def::TypeDef;
use super::maybe_empty_string_to_option; use super::maybe_empty_string_to_option;
#[derive(Serialize, TypeDef)] #[derive(Serialize, TypeDef, schemars::JsonSchema)]
#[serde(rename = "WebxdcMessageInfo", rename_all = "camelCase")] #[serde(rename = "WebxdcMessageInfo", rename_all = "camelCase")]
pub struct WebxdcMessageInfo { pub struct WebxdcMessageInfo {
/// The name of the app. /// The name of the app.

View File

@@ -21,7 +21,7 @@ serde_json = "1.0.96"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.28.0", features = ["io-std"] } tokio = { version = "1.28.0", features = ["io-std"] }
tokio-util = "0.7.8" tokio-util = "0.7.8"
yerpc = { version = "0.4.0", features = ["anyhow_expose"] } yerpc = { version = "0.5.1", features = ["anyhow_expose"] }
[features] [features]
default = ["vendored"] default = ["vendored"]