diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index cd6dc5196..884b69ac8 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -1,10 +1,13 @@ #![allow(dead_code, unused_variables)] use request::{ - endpoint::{ApiEndpoint, ApiEndpointUrl}, + endpoint::{ApiBaseUrl, ApiEndpointUrl}, + plugins_request_builder::PluginsRequestBuilder, + users_request_builder::UsersRequestBuilder, RequestMethod, WPNetworkRequest, WPNetworkResponse, }; -use std::collections::HashMap; +use serde::Serialize; +use std::{collections::HashMap, sync::Arc}; use url::Url; pub use api_error::{WPApiError, WPRestError, WPRestErrorCode, WPRestErrorWrapper}; @@ -25,8 +28,9 @@ const CONTENT_TYPE_JSON: &str = "application/json"; #[derive(Debug, uniffi::Object)] pub struct WPApiHelper { - api_endpoint: ApiEndpoint, - authentication: WPAuthentication, + request_builder: Arc, + users_request: UsersRequestBuilder, + plugins_request: PluginsRequestBuilder, } #[uniffi::export] @@ -43,22 +47,25 @@ impl WPApiHelper { pub fn new(site_url: String, authentication: WPAuthentication) -> Self { let url = Url::parse(site_url.as_str()).unwrap(); // TODO: Handle the url parse error - let api_endpoint = ApiEndpoint::new_from_str(site_url.as_str()).unwrap(); + let api_base_url = Arc::new(ApiBaseUrl::new(site_url.as_str()).unwrap()); + let request_builder = Arc::new(RequestBuilder { + authentication: authentication.clone(), + }); Self { - api_endpoint, - authentication, + request_builder: request_builder.clone(), + users_request: UsersRequestBuilder::new(api_base_url.clone(), request_builder.clone()), + plugins_request: PluginsRequestBuilder::new( + api_base_url.clone(), + request_builder.clone(), + ), } } // TODO: Remove this because we want to build all requests within the crate pub fn raw_request(&self, url: String) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: ApiEndpointUrl::new(Url::parse(url.as_str()).unwrap()).into(), - header_map: self.header_map(), - body: None, - } + self.request_builder + .get(ApiEndpointUrl::new(Url::parse(url.as_str()).unwrap())) } pub fn list_users_request( @@ -66,16 +73,7 @@ impl WPApiHelper { context: WPContext, params: &Option, // UniFFI doesn't support Option<&T> ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .users - .list(context, params.as_ref()) - .into(), - header_map: self.header_map(), - body: None, - } + self.users_request.list(context, params) } pub fn filter_list_users_request( @@ -84,25 +82,11 @@ impl WPApiHelper { params: &Option, // UniFFI doesn't support Option<&T> fields: &[SparseUserField], ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .users - .filter_list(context, params.as_ref(), fields) - .into(), - header_map: self.header_map(), - body: None, - } + self.users_request.filter_list(context, params, fields) } pub fn retrieve_user_request(&self, user_id: UserId, context: WPContext) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self.api_endpoint.users.retrieve(user_id, context).into(), - header_map: self.header_map(), - body: None, - } + self.users_request.retrieve(user_id, context) } pub fn filter_retrieve_user_request( @@ -111,25 +95,11 @@ impl WPApiHelper { context: WPContext, fields: &[SparseUserField], ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .users - .filter_retrieve(user_id, context, fields) - .into(), - header_map: self.header_map(), - body: None, - } + self.users_request.filter_retrieve(user_id, context, fields) } pub fn retrieve_current_user_request(&self, context: WPContext) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self.api_endpoint.users.retrieve_me(context).into(), - header_map: self.header_map(), - body: None, - } + self.users_request.retrieve_me(context) } pub fn filter_retrieve_current_user_request( @@ -137,25 +107,11 @@ impl WPApiHelper { context: WPContext, fields: &[SparseUserField], ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .users - .filter_retrieve_me(context, fields) - .into(), - header_map: self.header_map(), - body: None, - } + self.users_request.filter_retrieve_me(context, fields) } pub fn create_user_request(&self, params: &UserCreateParams) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::POST, - url: self.api_endpoint.users.create().into(), - header_map: self.header_map_for_post_request(), - body: serde_json::to_vec(¶ms).ok(), - } + self.users_request.create(params) } pub fn update_user_request( @@ -163,21 +119,11 @@ impl WPApiHelper { user_id: UserId, params: &UserUpdateParams, ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::POST, - url: self.api_endpoint.users.update(user_id).into(), - header_map: self.header_map_for_post_request(), - body: serde_json::to_vec(¶ms).ok(), - } + self.users_request.update(user_id, params) } pub fn update_current_user_request(&self, params: &UserUpdateParams) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::POST, - url: self.api_endpoint.users.update_me().into(), - header_map: self.header_map_for_post_request(), - body: serde_json::to_vec(¶ms).ok(), - } + self.users_request.update_me(params) } pub fn delete_user_request( @@ -185,21 +131,11 @@ impl WPApiHelper { user_id: UserId, params: &UserDeleteParams, ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::DELETE, - url: self.api_endpoint.users.delete(user_id, params).into(), - header_map: self.header_map(), - body: None, - } + self.users_request.delete(user_id, params) } pub fn delete_current_user_request(&self, params: &UserDeleteParams) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::DELETE, - url: self.api_endpoint.users.delete_me(params).into(), - header_map: self.header_map(), - body: None, - } + self.users_request.delete_me(params) } pub fn list_plugins_request( @@ -207,16 +143,7 @@ impl WPApiHelper { context: WPContext, params: &Option, // UniFFI doesn't support Option<&T> ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .plugins - .list(context, params.as_ref()) - .into(), - header_map: self.header_map(), - body: None, - } + self.plugins_request.list(context, params) } pub fn filter_list_plugins_request( @@ -225,25 +152,11 @@ impl WPApiHelper { params: &Option, // UniFFI doesn't support Option<&T> fields: &[SparsePluginField], ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .plugins - .filter_list(context, params.as_ref(), fields) - .into(), - header_map: self.header_map(), - body: None, - } + self.plugins_request.filter_list(context, params, fields) } pub fn create_plugin_request(&self, params: &PluginCreateParams) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::POST, - url: self.api_endpoint.plugins.create().into(), - header_map: self.header_map_for_post_request(), - body: serde_json::to_vec(¶ms).ok(), - } + self.plugins_request.create(params) } pub fn retrieve_plugin_request( @@ -251,12 +164,7 @@ impl WPApiHelper { context: WPContext, plugin: &PluginSlug, ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self.api_endpoint.plugins.retrieve(context, plugin).into(), - header_map: self.header_map(), - body: None, - } + self.plugins_request.retrieve(context, plugin) } pub fn filter_retrieve_plugin_request( @@ -265,16 +173,8 @@ impl WPApiHelper { plugin: &PluginSlug, fields: &[SparsePluginField], ) -> WPNetworkRequest { - WPNetworkRequest { - method: RequestMethod::GET, - url: self - .api_endpoint - .plugins - .filter_retrieve(context, plugin, fields) - .into(), - header_map: self.header_map(), - body: None, - } + self.plugins_request + .filter_retrieve(context, plugin, fields) } pub fn update_plugin_request( @@ -282,18 +182,45 @@ impl WPApiHelper { plugin: &PluginSlug, params: &PluginUpdateParams, ) -> WPNetworkRequest { + self.plugins_request.update(plugin, params) + } + + pub fn delete_plugin_request(&self, plugin: &PluginSlug) -> WPNetworkRequest { + self.plugins_request.delete(plugin) + } +} + +#[derive(Debug)] +struct RequestBuilder { + authentication: WPAuthentication, +} + +impl RequestBuilder { + fn get(&self, url: ApiEndpointUrl) -> WPNetworkRequest { + WPNetworkRequest { + method: RequestMethod::GET, + url: url.into(), + header_map: self.header_map(), + body: None, + } + } + + fn post(&self, url: ApiEndpointUrl, json_body: &T) -> WPNetworkRequest + where + T: ?Sized + Serialize, + { WPNetworkRequest { method: RequestMethod::POST, - url: self.api_endpoint.plugins.update(plugin).into(), + url: url.into(), header_map: self.header_map_for_post_request(), - body: serde_json::to_vec(¶ms).ok(), + body: serde_json::to_vec(json_body).ok(), } } - pub fn delete_plugin_request(&self, plugin: &PluginSlug) -> WPNetworkRequest { + fn delete(&self, url: ApiEndpointUrl) -> WPNetworkRequest { WPNetworkRequest { method: RequestMethod::DELETE, - url: self.api_endpoint.plugins.delete(plugin).into(), + url: url.into(), header_map: self.header_map(), body: None, } @@ -305,9 +232,9 @@ impl WPApiHelper { http::header::ACCEPT.to_string(), CONTENT_TYPE_JSON.to_string(), ); - match &self.authentication { + match self.authentication { WPAuthentication::None => None, - WPAuthentication::AuthorizationHeader { token } => { + WPAuthentication::AuthorizationHeader { ref token } => { header_map.insert("Authorization".to_string(), format!("Basic {}", token)) } }; diff --git a/wp_api/src/request.rs b/wp_api/src/request.rs index 9132e940d..35c7ab522 100644 --- a/wp_api/src/request.rs +++ b/wp_api/src/request.rs @@ -8,6 +8,8 @@ use crate::WPApiError; use self::endpoint::WpEndpointUrl; pub mod endpoint; +pub mod plugins_request_builder; +pub mod users_request_builder; // Has custom `Debug` trait implementation #[derive(uniffi::Record)] diff --git a/wp_api/src/request/endpoint.rs b/wp_api/src/request/endpoint.rs index c670b0f06..0407cbeb5 100644 --- a/wp_api/src/request/endpoint.rs +++ b/wp_api/src/request/endpoint.rs @@ -1,12 +1,9 @@ use url::Url; -use plugins_endpoint::*; -use users_endpoint::*; - use crate::SparseField; -mod plugins_endpoint; -mod users_endpoint; +pub(crate) mod plugins_endpoint; +pub(crate) mod users_endpoint; const WP_JSON_PATH_SEGMENTS: [&str; 3] = ["wp-json", "wp", "v2"]; @@ -83,27 +80,6 @@ impl ApiBaseUrl { } } -#[derive(Debug)] -pub(crate) struct ApiEndpoint { - pub base_url: ApiBaseUrl, - pub users: UsersEndpoint, - pub plugins: PluginsEndpoint, -} - -impl ApiEndpoint { - pub fn new(api_base_url: ApiBaseUrl) -> Self { - Self { - base_url: api_base_url.clone(), - users: UsersEndpoint::new(api_base_url.clone()), - plugins: PluginsEndpoint::new(api_base_url.clone()), - } - } - - pub fn new_from_str(site_base_url: &str) -> Result { - ApiBaseUrl::new(site_base_url).map(Self::new) - } -} - trait UrlExtension { fn append(self, segment: &str) -> Result; fn extend(self, segments: I) -> Result @@ -144,6 +120,8 @@ impl UrlExtension for Url { #[cfg(test)] mod tests { + use std::sync::Arc; + use super::*; use rstest::*; @@ -198,8 +176,8 @@ mod tests { } #[fixture] - pub fn fixture_api_base_url() -> ApiBaseUrl { - ApiBaseUrl::new("https://example.com").unwrap() + pub fn fixture_api_base_url() -> Arc { + ApiBaseUrl::new("https://example.com").unwrap().into() } pub fn validate_endpoint(endpoint_url: ApiEndpointUrl, path: &str) { diff --git a/wp_api/src/request/endpoint/plugins_endpoint.rs b/wp_api/src/request/endpoint/plugins_endpoint.rs index 20e6f51ab..6aa5b6300 100644 --- a/wp_api/src/request/endpoint/plugins_endpoint.rs +++ b/wp_api/src/request/endpoint/plugins_endpoint.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use url::Url; use crate::{plugins::PluginListParams, PluginSlug, SparsePluginField, WPContext}; @@ -6,11 +8,11 @@ use super::{ApiBaseUrl, ApiEndpointUrl, UrlExtension}; #[derive(Debug)] pub(crate) struct PluginsEndpoint { - api_base_url: ApiBaseUrl, + api_base_url: Arc, } impl PluginsEndpoint { - pub fn new(api_base_url: ApiBaseUrl) -> Self { + pub fn new(api_base_url: Arc) -> Self { Self { api_base_url } } @@ -84,7 +86,7 @@ mod tests { use crate::{ generate, request::endpoint::tests::{fixture_api_base_url, validate_endpoint}, - ApiEndpoint, PluginStatus, + PluginStatus, }; use rstest::*; @@ -238,7 +240,7 @@ mod tests { } #[fixture] - fn plugins_endpoint(fixture_api_base_url: ApiBaseUrl) -> PluginsEndpoint { - ApiEndpoint::new(fixture_api_base_url).plugins + fn plugins_endpoint(fixture_api_base_url: Arc) -> PluginsEndpoint { + PluginsEndpoint::new(fixture_api_base_url) } } diff --git a/wp_api/src/request/endpoint/users_endpoint.rs b/wp_api/src/request/endpoint/users_endpoint.rs index e6ed0a7d3..9d4c7acec 100644 --- a/wp_api/src/request/endpoint/users_endpoint.rs +++ b/wp_api/src/request/endpoint/users_endpoint.rs @@ -1,14 +1,16 @@ +use std::sync::Arc; + use crate::{SparseUserField, UserDeleteParams, UserId, UserListParams, WPContext}; use super::{ApiBaseUrl, ApiEndpointUrl, UrlExtension}; #[derive(Debug)] pub(crate) struct UsersEndpoint { - api_base_url: ApiBaseUrl, + api_base_url: Arc, } impl UsersEndpoint { - pub fn new(api_base_url: ApiBaseUrl) -> Self { + pub fn new(api_base_url: Arc) -> Self { Self { api_base_url } } @@ -105,10 +107,7 @@ impl UsersEndpoint { #[cfg(test)] mod tests { use super::*; - use crate::{ - request::endpoint::tests::{fixture_api_base_url, validate_endpoint}, - ApiEndpoint, - }; + use crate::request::endpoint::tests::{fixture_api_base_url, validate_endpoint}; use rstest::*; #[rstest] @@ -243,7 +242,7 @@ mod tests { } #[fixture] - fn users_endpoint(fixture_api_base_url: ApiBaseUrl) -> UsersEndpoint { - ApiEndpoint::new(fixture_api_base_url).users + fn users_endpoint(fixture_api_base_url: Arc) -> UsersEndpoint { + UsersEndpoint::new(fixture_api_base_url) } } diff --git a/wp_api/src/request/plugins_request_builder.rs b/wp_api/src/request/plugins_request_builder.rs new file mode 100644 index 000000000..e974e8e39 --- /dev/null +++ b/wp_api/src/request/plugins_request_builder.rs @@ -0,0 +1,73 @@ +use std::sync::Arc; + +use crate::{ + PluginCreateParams, PluginListParams, PluginSlug, PluginUpdateParams, RequestBuilder, + SparsePluginField, WPContext, +}; + +use super::{ + endpoint::{plugins_endpoint::PluginsEndpoint, ApiBaseUrl}, + WPNetworkRequest, +}; + +#[derive(Debug)] +pub(crate) struct PluginsRequestBuilder { + endpoint: PluginsEndpoint, + request_builder: Arc, +} + +impl PluginsRequestBuilder { + pub fn new(api_base_url: Arc, request_builder: Arc) -> Self { + Self { + endpoint: PluginsEndpoint::new(api_base_url), + request_builder, + } + } + + pub fn list( + &self, + context: WPContext, + params: &Option, // UniFFI doesn't support Option<&T> + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.list(context, params.as_ref())) + } + + pub fn filter_list( + &self, + context: WPContext, + params: &Option, // UniFFI doesn't support Option<&T> + fields: &[SparsePluginField], + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.filter_list(context, params.as_ref(), fields)) + } + + pub fn create(&self, params: &PluginCreateParams) -> WPNetworkRequest { + self.request_builder.post(self.endpoint.create(), params) + } + + pub fn retrieve(&self, context: WPContext, plugin: &PluginSlug) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.retrieve(context, plugin)) + } + + pub fn filter_retrieve( + &self, + context: WPContext, + plugin: &PluginSlug, + fields: &[SparsePluginField], + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.filter_retrieve(context, plugin, fields)) + } + + pub fn update(&self, plugin: &PluginSlug, params: &PluginUpdateParams) -> WPNetworkRequest { + self.request_builder + .post(self.endpoint.update(plugin), params) + } + + pub fn delete(&self, plugin: &PluginSlug) -> WPNetworkRequest { + self.request_builder.delete(self.endpoint.delete(plugin)) + } +} diff --git a/wp_api/src/request/users_request_builder.rs b/wp_api/src/request/users_request_builder.rs new file mode 100644 index 000000000..b1a25eefa --- /dev/null +++ b/wp_api/src/request/users_request_builder.rs @@ -0,0 +1,95 @@ +use std::sync::Arc; + +use crate::{ + RequestBuilder, SparseUserField, UserCreateParams, UserDeleteParams, UserId, UserListParams, + UserUpdateParams, WPContext, +}; + +use super::{ + endpoint::{users_endpoint::UsersEndpoint, ApiBaseUrl}, + WPNetworkRequest, +}; + +#[derive(Debug)] +pub(crate) struct UsersRequestBuilder { + endpoint: UsersEndpoint, + request_builder: Arc, +} + +impl UsersRequestBuilder { + pub fn new(api_base_url: Arc, request_builder: Arc) -> Self { + Self { + endpoint: UsersEndpoint::new(api_base_url), + request_builder, + } + } + + pub fn list( + &self, + context: WPContext, + params: &Option, // UniFFI doesn't support Option<&T> + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.list(context, params.as_ref())) + } + + pub fn filter_list( + &self, + context: WPContext, + params: &Option, // UniFFI doesn't support Option<&T> + fields: &[SparseUserField], + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.filter_list(context, params.as_ref(), fields)) + } + + pub fn retrieve(&self, user_id: UserId, context: WPContext) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.retrieve(user_id, context)) + } + + pub fn filter_retrieve( + &self, + user_id: UserId, + context: WPContext, + fields: &[SparseUserField], + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.filter_retrieve(user_id, context, fields)) + } + + pub fn retrieve_me(&self, context: WPContext) -> WPNetworkRequest { + self.request_builder.get(self.endpoint.retrieve_me(context)) + } + + pub fn filter_retrieve_me( + &self, + context: WPContext, + fields: &[SparseUserField], + ) -> WPNetworkRequest { + self.request_builder + .get(self.endpoint.filter_retrieve_me(context, fields)) + } + + pub fn create(&self, params: &UserCreateParams) -> WPNetworkRequest { + self.request_builder.post(self.endpoint.create(), params) + } + + pub fn update(&self, user_id: UserId, params: &UserUpdateParams) -> WPNetworkRequest { + self.request_builder + .post(self.endpoint.update(user_id), params) + } + + pub fn update_me(&self, params: &UserUpdateParams) -> WPNetworkRequest { + self.request_builder.post(self.endpoint.update_me(), params) + } + + pub fn delete(&self, user_id: UserId, params: &UserDeleteParams) -> WPNetworkRequest { + self.request_builder + .delete(self.endpoint.delete(user_id, params)) + } + + pub fn delete_me(&self, params: &UserDeleteParams) -> WPNetworkRequest { + self.request_builder.delete(self.endpoint.delete_me(params)) + } +}