diff --git a/fastlane/Fastfile b/fastlane/Fastfile index cc7da943e..c64c3401c 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -21,7 +21,6 @@ lane :release do |options| build_xcframework update_swift_package publish_github_release - # TODO: publish android library end lane :validate do diff --git a/wp_api/src/lib.rs b/wp_api/src/lib.rs index 358041f83..01597c24b 100644 --- a/wp_api/src/lib.rs +++ b/wp_api/src/lib.rs @@ -2,11 +2,9 @@ use request::{ endpoint::{ - application_passwords_endpoint::{ - ApplicationPasswordsRequestBuilder2, ApplicationPasswordsRequestExecutor, - }, - plugins_endpoint::{PluginsRequestBuilder2, PluginsRequestExecutor}, - users_endpoint::{UsersRequestBuilder2, UsersRequestExecutor}, + application_passwords_endpoint::ApplicationPasswordsRequestExecutor, + plugins_endpoint::PluginsRequestExecutor, + users_endpoint::{UsersRequestBuilder, UsersRequestExecutor}, ApiBaseUrl, }, RequestExecutor, WpNetworkResponse, @@ -30,39 +28,27 @@ pub mod users; #[cfg(test)] mod unit_test_common; -// TODO: This is a temporary type that allows building a request type -// Although we'll have a type that does that, it's unlikely that it'll look like this. -// It still does its job for now to prove that `UsersRequestBuilder2` (temporary) type is -// properly generated and utilized in `test_manual_request_builder_immut` integration tests #[derive(Debug, uniffi::Object)] pub struct WpApiRequestBuilder { - users: Arc, + users: Arc, } #[uniffi::export] impl WpApiRequestBuilder { #[uniffi::constructor] - pub fn new( - site_url: String, - authentication: WpAuthentication, - request_executor: Arc, - ) -> Result { + pub fn new(site_url: String, authentication: WpAuthentication) -> Result { let api_base_url: Arc = ApiBaseUrl::try_from(site_url.as_str()) .map_err(|err| WpApiError::SiteUrlParsingError { reason: err.to_string(), })? .into(); - let request_builder = Arc::new(request::RequestBuilder::new( - request_executor, - authentication.clone(), - )); Ok(Self { - users: UsersRequestBuilder2::new(api_base_url.clone(), request_builder.clone()).into(), + users: UsersRequestBuilder::new(api_base_url.clone(), authentication).into(), }) } - pub fn users(&self) -> Arc { + pub fn users(&self) -> Arc { self.users.clone() } } @@ -87,27 +73,23 @@ impl WpRequestBuilder { reason: err.to_string(), })? .into(); - let request_builder = Arc::new(request::RequestBuilder::new( - request_executor.clone(), - authentication.clone(), - )); Ok(Self { application_passwords: ApplicationPasswordsRequestExecutor::new( - ApplicationPasswordsRequestBuilder2::new( - api_base_url.clone(), - request_builder.clone(), - ), + api_base_url.clone(), + authentication.clone(), request_executor.clone(), ) .into(), users: UsersRequestExecutor::new( - UsersRequestBuilder2::new(api_base_url.clone(), request_builder.clone()), + api_base_url.clone(), + authentication.clone(), request_executor.clone(), ) .into(), plugins: PluginsRequestExecutor::new( - PluginsRequestBuilder2::new(api_base_url.clone(), request_builder.clone()), + api_base_url.clone(), + authentication.clone(), request_executor.clone(), ) .into(), diff --git a/wp_api/src/request.rs b/wp_api/src/request.rs index 5adadd43b..c0c5d47b9 100644 --- a/wp_api/src/request.rs +++ b/wp_api/src/request.rs @@ -1,7 +1,7 @@ -use std::{collections::HashMap, fmt::Debug, sync::Arc}; +use std::{collections::HashMap, fmt::Debug}; use endpoint::ApiEndpointUrl; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use url::Url; use crate::{api_error::RequestExecutionError, WpApiError, WpAuthentication}; @@ -14,23 +14,16 @@ const CONTENT_TYPE_JSON: &str = "application/json"; const LINK_HEADER_KEY: &str = "Link"; #[derive(Debug)] -pub(crate) struct RequestBuilder { - executor: Arc, +struct InnerRequestBuilder { authentication: WpAuthentication, } -impl RequestBuilder { - pub(crate) fn new( - executor: Arc, - authentication: WpAuthentication, - ) -> Self { - Self { - executor, - authentication, - } +impl InnerRequestBuilder { + fn new(authentication: WpAuthentication) -> Self { + Self { authentication } } - fn build_get_request(&self, url: ApiEndpointUrl) -> WpNetworkRequest { + fn get(&self, url: ApiEndpointUrl) -> WpNetworkRequest { WpNetworkRequest { method: RequestMethod::GET, url: url.into(), @@ -39,14 +32,7 @@ impl RequestBuilder { } } - async fn get(&self, url: ApiEndpointUrl) -> Result { - self.executor - .execute(self.build_get_request(url)) - .await? - .parse() - } - - fn build_post_request(&self, url: ApiEndpointUrl, json_body: &T) -> WpNetworkRequest + fn post(&self, url: ApiEndpointUrl, json_body: &T) -> WpNetworkRequest where T: ?Sized + Serialize, { @@ -58,18 +44,7 @@ impl RequestBuilder { } } - async fn post(&self, url: ApiEndpointUrl, json_body: &T) -> Result - where - T: ?Sized + Serialize, - R: DeserializeOwned, - { - self.executor - .execute(self.build_post_request(url, json_body)) - .await? - .parse() - } - - fn build_delete_request(&self, url: ApiEndpointUrl) -> WpNetworkRequest { + fn delete(&self, url: ApiEndpointUrl) -> WpNetworkRequest { WpNetworkRequest { method: RequestMethod::DELETE, url: url.into(), @@ -78,13 +53,6 @@ impl RequestBuilder { } } - async fn delete(&self, url: ApiEndpointUrl) -> Result { - self.executor - .execute(self.build_delete_request(url)) - .await? - .parse() - } - fn header_map(&self) -> HashMap { let mut header_map = HashMap::new(); header_map.insert( diff --git a/wp_api/tests/test_manual_request_builder_immut.rs b/wp_api/tests/test_manual_request_builder_immut.rs index ecca5d5ad..8867ab94c 100644 --- a/wp_api/tests/test_manual_request_builder_immut.rs +++ b/wp_api/tests/test_manual_request_builder_immut.rs @@ -5,7 +5,6 @@ use integration_test_common::{ use reusable_test_cases::list_users_cases; use rstest::*; use rstest_reuse::{self, apply}; -use std::sync::Arc; use wp_api::{ generate, users::UserWithEditContext, @@ -26,16 +25,11 @@ async fn list_users_with_edit_context(#[case] params: UserListParams) { TEST_CREDENTIALS_ADMIN_USERNAME.to_string(), TEST_CREDENTIALS_ADMIN_PASSWORD.to_string(), ); - let async_wp_networking = Arc::new(AsyncWpNetworking::default()); + let async_wp_networking = AsyncWpNetworking::default(); - let request_builder = WpApiRequestBuilder::new( - TEST_CREDENTIALS_SITE_URL.to_string(), - authentication, - // TODO: A request executor shouldn't be necessary, but we don't have a standalone request - // builder yet - async_wp_networking.clone(), - ) - .expect("Site url is generated by our tooling"); + let request_builder = + WpApiRequestBuilder::new(TEST_CREDENTIALS_SITE_URL.to_string(), authentication) + .expect("Site url is generated by our tooling"); let wp_request = request_builder.users().list_with_edit_context(¶ms); let response = async_wp_networking.async_request(wp_request).await; let result = response.unwrap().parse::>(); diff --git a/wp_derive_request_builder/src/generate.rs b/wp_derive_request_builder/src/generate.rs index 69d11464d..3f21e96a2 100644 --- a/wp_derive_request_builder/src/generate.rs +++ b/wp_derive_request_builder/src/generate.rs @@ -28,11 +28,13 @@ pub(crate) fn generate_types(parsed_enum: &ParsedEnum) -> TokenStream { } fn generate_async_request_executor(config: &Config, parsed_enum: &ParsedEnum) -> TokenStream { - let api_base_url_type = &config.api_base_url_type; - let request_builder_ident = &config.request_builder_ident; - let request_executor_ident = &config.request_executor_ident; - let request_executor_type = &config.request_executor_type; - let wp_api_error_type = &config.wp_api_error_type; + let static_api_base_url_type = &config.static_types.api_base_url; + let static_wp_authentication_type = &config.static_types.wp_authentication; + let static_inner_request_builder_type = &config.static_types.inner_request_builder; + let static_request_executor_type = &config.static_types.request_executor; + let static_wp_api_error_type = &config.static_types.wp_api_error; + let generated_request_builder_ident = &config.generated_idents.request_builder; + let generated_request_executor_ident = &config.generated_idents.request_executor; let functions = parsed_enum.variants.iter().map(|variant| { let url_parts = variant.attr.url_parts.as_slice(); @@ -60,7 +62,7 @@ fn generate_async_request_executor(config: &Config, parsed_enum: &ParsedEnum) -> &config.sparse_field_type, ); quote! { - pub async #fn_signature -> Result<#output_type, #wp_api_error_type> { + pub async #fn_signature -> Result<#output_type, #static_wp_api_error_type> { #request_from_request_builder self.request_executor.execute(request).await?.parse() } @@ -71,31 +73,32 @@ fn generate_async_request_executor(config: &Config, parsed_enum: &ParsedEnum) -> quote! { #[derive(Debug, uniffi::Object)] - pub struct #request_executor_ident { - request_builder: #request_builder_ident, - request_executor: #request_executor_type, + pub struct #generated_request_executor_ident { + request_builder: #generated_request_builder_ident, + request_executor: #static_request_executor_type, } - impl #request_executor_ident { - pub(crate) fn new(request_builder: #request_builder_ident, request_executor: #request_executor_type) -> Self { + impl #generated_request_executor_ident { + pub fn new(api_base_url: #static_api_base_url_type, authentication: #static_wp_authentication_type, request_executor: #static_request_executor_type) -> Self { Self { - request_builder, + request_builder: #generated_request_builder_ident::new(api_base_url, authentication), request_executor, } } } #[uniffi::export] - impl #request_executor_ident { + impl #generated_request_executor_ident { #(#functions)* } } } fn generate_request_builder(config: &Config, parsed_enum: &ParsedEnum) -> TokenStream { - let api_base_url_type = &config.api_base_url_type; - let endpoint_ident = &config.endpoint_ident; - let request_builder_ident = &config.request_builder_ident; - let request_builder_type = &config.request_builder_type; - let wp_network_request_type = &config.wp_network_request_type; + let static_api_base_url_type = &config.static_types.api_base_url; + let static_inner_request_builder_type = &config.static_types.inner_request_builder; + let static_wp_authentication_type = &config.static_types.wp_authentication; + let static_wp_network_request_type = &config.static_types.wp_network_request; + let generated_endpoint_ident = &config.generated_idents.endpoint; + let generated_request_builder_ident = &config.generated_idents.request_builder; let functions = parsed_enum.variants.iter().map(|variant| { let url_parts = variant.attr.url_parts.as_slice(); @@ -123,7 +126,7 @@ fn generate_request_builder(config: &Config, parsed_enum: &ParsedEnum) -> TokenS let fn_body_build_request_from_url = fn_body_build_request_from_url(params_type, variant.attr.request_type); quote! { - pub #fn_signature -> #wp_network_request_type { + pub #fn_signature -> #static_wp_network_request_type { #url_from_endpoint #fn_body_build_request_from_url } @@ -134,28 +137,29 @@ fn generate_request_builder(config: &Config, parsed_enum: &ParsedEnum) -> TokenS quote! { #[derive(Debug, uniffi::Object)] - pub struct #request_builder_ident { - endpoint: #endpoint_ident, - request_builder: #request_builder_type, + pub struct #generated_request_builder_ident { + endpoint: #generated_endpoint_ident, + inner: #static_inner_request_builder_type, } - impl #request_builder_ident { - pub(crate) fn new(api_base_url: #api_base_url_type, request_builder: #request_builder_type) -> Self { + impl #generated_request_builder_ident { + pub fn new(api_base_url: #static_api_base_url_type, authentication: #static_wp_authentication_type) -> Self { Self { - endpoint: #endpoint_ident::new(api_base_url), - request_builder, + endpoint: #generated_endpoint_ident::new(api_base_url), + inner: #static_inner_request_builder_type::new(authentication), } } } #[uniffi::export] - impl #request_builder_ident { + impl #generated_request_builder_ident { #(#functions)* } } } fn generate_endpoint_type(config: &Config, parsed_enum: &ParsedEnum) -> TokenStream { - let api_base_url_type = &config.api_base_url_type; - let endpoint_ident = &config.endpoint_ident; + let static_api_base_url_type = &config.static_types.api_base_url; + let static_api_endpoint_url_type = &config.static_types.api_endpoint_url; + let generated_endpoint_ident = &config.generated_idents.endpoint; let functions = parsed_enum.variants.iter().map(|variant| { let url_parts = variant.attr.url_parts.as_slice(); @@ -178,11 +182,10 @@ fn generate_endpoint_type(config: &Config, parsed_enum: &ParsedEnum) -> TokenStr ); let context_query_pair = fn_body_context_query_pairs(&config.crate_ident, context_and_filter_handler); - let api_endpoint_url_type = &config.api_endpoint_url_type; let fields_query_pairs = fn_body_fields_query_pairs(&config.crate_ident, context_and_filter_handler); quote! { - pub #fn_signature -> #api_endpoint_url_type { + pub #fn_signature -> #static_api_endpoint_url_type { #url_from_api_base_url #context_query_pair #query_pairs @@ -196,12 +199,12 @@ fn generate_endpoint_type(config: &Config, parsed_enum: &ParsedEnum) -> TokenStr quote! { #[derive(Debug)] - pub struct #endpoint_ident { - api_base_url: #api_base_url_type, + pub struct #generated_endpoint_ident { + api_base_url: #static_api_base_url_type, } - impl #endpoint_ident { - pub fn new(api_base_url: #api_base_url_type) -> Self { + impl #generated_endpoint_ident { + pub fn new(api_base_url: #static_api_base_url_type) -> Self { Self { api_base_url } } @@ -263,19 +266,10 @@ impl Display for WpContext { #[derive(Debug)] pub struct Config { - // TODO: It's not clear what some of the names refer to and the difference between them - // For example, with "request_builder_ident" & "request_builder_type" - pub api_base_url_type: TokenStream, - pub api_endpoint_url_type: TokenStream, pub crate_ident: Ident, - pub endpoint_ident: Ident, - pub request_builder_ident: Ident, - pub request_builder_type: TokenStream, - pub request_executor_ident: Ident, - pub request_executor_type: TokenStream, pub sparse_field_type: SparseFieldAttr, - pub wp_api_error_type: TokenStream, - pub wp_network_request_type: TokenStream, + pub generated_idents: ConfigGeneratedIdents, + pub static_types: ConfigStaticTypes, } impl Config { @@ -288,28 +282,56 @@ impl Config { FoundCrate::Itself => format_ident!("crate"), FoundCrate::Name(name) => Ident::new(&name, Span::call_site()), }; - let api_base_url_type = - quote! { std::sync::Arc<#crate_ident::request::endpoint::ApiBaseUrl> }; - let api_endpoint_url_type = quote! { #crate_ident::request::endpoint::ApiEndpointUrl }; - let request_builder_type = quote! { std::sync::Arc<#crate_ident::request::RequestBuilder> }; - let request_executor_type = - quote! { std::sync::Arc }; - let wp_api_error_type = quote! { #crate_ident::WpApiError }; - let wp_network_request_type = quote! { #crate_ident::request::WpNetworkRequest }; + let generated_idents = ConfigGeneratedIdents::new(parsed_enum); + let static_types = ConfigStaticTypes::new(&crate_ident); + Self { - api_base_url_type, - api_endpoint_url_type, crate_ident, - endpoint_ident: format_ident!("{}Endpoint", parsed_enum.enum_ident), - // TODO: We use `2` suffix here to prevent the name clash with the current - // implementation - request_builder_ident: format_ident!("{}Builder2", parsed_enum.enum_ident), - request_builder_type, - request_executor_ident: format_ident!("{}Executor", parsed_enum.enum_ident), - request_executor_type, sparse_field_type: parsed_enum.sparse_field_attr.clone(), - wp_api_error_type, - wp_network_request_type, + generated_idents, + static_types, + } + } +} + +#[derive(Debug)] +pub struct ConfigStaticTypes { + pub api_base_url: TokenStream, + pub api_endpoint_url: TokenStream, + pub inner_request_builder: TokenStream, + pub request_executor: TokenStream, + pub wp_api_error: TokenStream, + pub wp_authentication: TokenStream, + pub wp_network_request: TokenStream, +} + +impl ConfigStaticTypes { + fn new(crate_ident: &Ident) -> Self { + Self { + api_base_url: quote! { std::sync::Arc<#crate_ident::request::endpoint::ApiBaseUrl> }, + api_endpoint_url: quote! { #crate_ident::request::endpoint::ApiEndpointUrl }, + inner_request_builder: quote! { #crate_ident::request::InnerRequestBuilder }, + request_executor: quote! { std::sync::Arc }, + wp_api_error: quote! { #crate_ident::WpApiError }, + wp_authentication: quote! { #crate_ident::WpAuthentication }, + wp_network_request: quote! { #crate_ident::request::WpNetworkRequest }, + } + } +} + +#[derive(Debug)] +pub struct ConfigGeneratedIdents { + pub endpoint: Ident, + pub request_builder: Ident, + pub request_executor: Ident, +} + +impl ConfigGeneratedIdents { + fn new(parsed_enum: &ParsedEnum) -> Self { + Self { + endpoint: format_ident!("{}Endpoint", parsed_enum.enum_ident), + request_builder: format_ident!("{}Builder", parsed_enum.enum_ident), + request_executor: format_ident!("{}Executor", parsed_enum.enum_ident), } } } diff --git a/wp_derive_request_builder/src/generate/helpers_to_generate_tokens.rs b/wp_derive_request_builder/src/generate/helpers_to_generate_tokens.rs index b891c4d25..585adef96 100644 --- a/wp_derive_request_builder/src/generate/helpers_to_generate_tokens.rs +++ b/wp_derive_request_builder/src/generate/helpers_to_generate_tokens.rs @@ -337,19 +337,19 @@ pub fn fn_body_build_request_from_url( ) -> TokenStream { match request_type { RequestType::ContextualGet => quote! { - self.request_builder.build_get_request(url) + self.inner.get(url) }, RequestType::Delete => quote! { - self.request_builder.build_delete_request(url) + self.inner.delete(url) }, RequestType::Post => { if params_type.tokens().is_some() { quote! { - self.request_builder.build_post_request(url, params) + self.inner.post(url, params) } } else { quote! { - self.request_builder.build_post_request(url) + self.inner.post(url) } } } @@ -1019,23 +1019,23 @@ mod tests { } #[rstest] - #[case(&ParamsType::new(None), RequestType::ContextualGet, "self . request_builder . build_get_request (url)")] + #[case(&ParamsType::new(None), RequestType::ContextualGet, "self . inner . get (url)")] #[case( &referenced_params_type("UserListParams"), RequestType::ContextualGet, - "self . request_builder . build_get_request (url)" + "self . inner . get (url)" )] - #[case(&ParamsType::new(None), RequestType::Delete, "self . request_builder . build_delete_request (url)")] + #[case(&ParamsType::new(None), RequestType::Delete, "self . inner . delete (url)")] #[case( &referenced_params_type("UserListParams"), RequestType::Delete, - "self . request_builder . build_delete_request (url)" + "self . inner . delete (url)" )] - #[case(&ParamsType::new(None), RequestType::Post, "self . request_builder . build_post_request (url)")] + #[case(&ParamsType::new(None), RequestType::Post, "self . inner . post (url)")] #[case( &referenced_params_type("UserListParams"), RequestType::Post, - "self . request_builder . build_post_request (url , params)" + "self . inner . post (url , params)" )] fn test_fn_body_build_request_from_url( #[case] params: &ParamsType,