Skip to content

Commit

Permalink
chore: Refactor to allow external adapters
Browse files Browse the repository at this point in the history
  • Loading branch information
fussybeaver committed Oct 19, 2024
1 parent 2087bbe commit 9c11683
Show file tree
Hide file tree
Showing 48 changed files with 27,723 additions and 20,668 deletions.
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ repository = "https://github.com/fussybeaver/roctogen"
documentation = "https://docs.rs/roctogen"
readme = "README.md"
keywords = ["github"]
edition = "2018"
edition = "2021"

[lib]
crate-type = ["cdylib", "rlib"]
path = "src/lib.rs"

[features]
default = []
reqwest = ["dep:reqwest", "dep:bytes"]

# Activate mock base url
mock = []
Expand All @@ -31,9 +32,10 @@ serde_json = {version = "1.0"}
serde_urlencoded = { version = "0.7" }
thiserror = "1"
log = "0.4"
bytes = { version = "1", optional = true }

# reqwest
reqwest = { version = "0.12", optional = true, features = ["json"] }
reqwest = { version = "0.12", optional = true, features = [] }

# ureq
ureq = { version = "3.0.0-rc1", optional = true, features = ["json"] }
Expand Down
55 changes: 31 additions & 24 deletions codegen/templates/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,26 @@

use serde::Deserialize;

use crate::adapters::{AdapterError, Client, FromJson, GitHubRequest, GitHubRequestBuilder, GitHubResponseExt};
use crate::adapters::{AdapterError, Client, GitHubRequest, GitHubResponseExt};
use crate::models::*;

use super::PerPage;

use std::collections::HashMap;
use serde_json::value::Value;

pub struct {{classname}}<'api, C: Client<Req = crate::adapters::Req>> {
pub struct {{classname}}<'api, C: Client> where AdapterError: From<<C as Client>::Err> {
client: &'api C
}
pub fn new<C: Client<Req = crate::adapters::Req>>(client: &C) -> {{classname}}<C> {
pub fn new<C: Client>(client: &C) -> {{classname}}<C> where AdapterError: From<<C as Client>::Err> {
{{classname}} { client }
}
{{#operations}}{{#operation}}{{#contents}}
/// Errors for the [{{summary}}]({{classname}}::{{operationId}}_async()) endpoint.
#[derive(Debug, thiserror::Error)]
pub enum {{classname}}{{operationIdCamelCase}}Error {
#[error(transparent)]
AdapterError(#[from] AdapterError),
#[error(transparent)]
SerdeJson(#[from] serde_json::Error),
#[error(transparent)]
SerdeUrl(#[from] serde_urlencoded::ser::Error),
// -- endpoint errors
{{#responses}}{{^vendorExtensions.x-is-default}}
#[error("{{{message}}}")]
Status{{code}}{{#dataType}}({{{.}}}){{/dataType}},
Expand All @@ -44,6 +34,23 @@ pub enum {{classname}}{{operationIdCamelCase}}Error {
Generic { code: u16 },
}
impl From<{{classname}}{{operationIdCamelCase}}Error> for AdapterError {
fn from(err: {{classname}}{{operationIdCamelCase}}Error) -> Self {
let (description, status_code) = match err {
{{#responses}}{{^vendorExtensions.x-is-default}}
{{classname}}{{operationIdCamelCase}}Error::Status{{code}}{{#dataType}}(_){{/dataType}} => (String::from("{{{message}}}"), {{code}}),
{{/vendorExtensions.x-is-default}}{{/responses}}
{{classname}}{{operationIdCamelCase}}Error::Generic { code } => (String::from("Generic"), code)
};
Self::Endpoint {
description,
status_code,
source: Some(Box::new(err))
}
}
}
{{/contents}}{{/operation}}
{{#operation}}{{#contents}}{{#hasQueryParams}}
Expand Down Expand Up @@ -86,7 +93,7 @@ impl<'enc> From<&'enc PerPage> for {{classname}}{{operationIdCamelCase}}Params{{
{{/hasQueryParams}}
{{/contents}}{{/operation}}
impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {
impl<'api, C: Client> {{classname}}<'api, C> where AdapterError: From<<C as Client>::Err> {
{{#operation}}{{#contents}}
/// ---
///
Expand All @@ -105,7 +112,7 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {
///
/// ---
{{#vendorExtensions.x-github.previews}}#[cfg(feature = "{{name}}")]
{{/vendorExtensions.x-github.previews}}pub async fn {{operationId}}_async(&self{{#hasParams}}, {{/hasParams}}{{#pathParams}}{{paramName}}: {{#nullable}}Option<{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}>{{/nullable}}{{^nullable}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}{{/nullable}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{#hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}query_params: {{#vendorExtensions.x-codegen-has-optional-query-params}}Option<{{/vendorExtensions.x-codegen-has-optional-query-params}}impl Into<{{classname}}{{operationIdCamelCase}}Params{{#vendorExtensions.x-codegen-has-string-params}}<'api>{{/vendorExtensions.x-codegen-has-string-params}}>{{#vendorExtensions.x-codegen-has-optional-query-params}}>{{/vendorExtensions.x-codegen-has-optional-query-params}}{{#hasBodyParam}}, {{/hasBodyParam}}{{/hasQueryParams}}{{#hasBodyParam}}{{^hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}{{/hasQueryParams}}body: {{#bodyParam}}{{{dataType}}}{{/bodyParam}}{{/hasBodyParam}}) -> Result<{{#responses}}{{#vendorExtensions.x-is-default}}{{{dataType}}}{{/vendorExtensions.x-is-default}}{{/responses}}{{#vendorExtensions.x-codegen-response-empty-default}}(){{/vendorExtensions.x-codegen-response-empty-default}}, {{classname}}{{operationIdCamelCase}}Error> {
{{/vendorExtensions.x-github.previews}}pub async fn {{operationId}}_async(&self{{#hasParams}}, {{/hasParams}}{{#pathParams}}{{paramName}}: {{#nullable}}Option<{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}>{{/nullable}}{{^nullable}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}{{/nullable}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{#hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}query_params: {{#vendorExtensions.x-codegen-has-optional-query-params}}Option<{{/vendorExtensions.x-codegen-has-optional-query-params}}impl Into<{{classname}}{{operationIdCamelCase}}Params{{#vendorExtensions.x-codegen-has-string-params}}<'api>{{/vendorExtensions.x-codegen-has-string-params}}>{{#vendorExtensions.x-codegen-has-optional-query-params}}>{{/vendorExtensions.x-codegen-has-optional-query-params}}{{#hasBodyParam}}, {{/hasBodyParam}}{{/hasQueryParams}}{{#hasBodyParam}}{{^hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}{{/hasQueryParams}}body: {{#bodyParam}}{{{dataType}}}{{/bodyParam}}{{/hasBodyParam}}) -> Result<{{#responses}}{{#vendorExtensions.x-is-default}}{{{dataType}}}{{/vendorExtensions.x-is-default}}{{/responses}}{{#vendorExtensions.x-codegen-response-empty-default}}(){{/vendorExtensions.x-codegen-response-empty-default}}, AdapterError> {

let {{#hasQueryParams}}mut {{/hasQueryParams}}request_uri = format!("{}{{path}}", super::GITHUB_BASE_API_URL{{#hasPathParams}}, {{/hasPathParams}}{{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}});

Expand All @@ -124,12 +131,12 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {

let req = GitHubRequest {
uri: request_uri,
body: {{#hasBodyParam}}Some({{#bodyParam}}{{^vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-is-map-container}}HashMap{{/vendorExtensions.x-is-map-container}}{{^vendorExtensions.x-is-map-container}}{{{dataType}}}{{/vendorExtensions.x-is-map-container}}::from_json(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-codegen-body-bytes}}body.into(){{/vendorExtensions.x-codegen-body-bytes}}{{/bodyParam}}){{/hasBodyParam}}{{^hasBodyParam}}None{{/hasBodyParam}},
body: {{#hasBodyParam}}Some(C::from_json::<{{#bodyParam}}{{^vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-is-map-container}}HashMap{{/vendorExtensions.x-is-map-container}}{{^vendorExtensions.x-is-map-container}}{{{dataType}}}{{/vendorExtensions.x-is-map-container}}>(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-codegen-body-bytes}}Vec<u8>>(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{/bodyParam}}){{/hasBodyParam}}{{^hasBodyParam}}None::<C::Body>{{/hasBodyParam}},
method: "{{httpMethod}}",
headers: vec![{{#vendorExtensions.x-github.previews}}("Accept", "application/vnd.github.{{name}}-preview+json"), {{/vendorExtensions.x-github.previews}}]
};

let request = GitHubRequestBuilder::build(req, self.client)?;
let request = self.client.build(req)?;

// --

Expand All @@ -142,9 +149,9 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {
} else {
match github_response.status_code() {
{{#responses}}{{#vendorExtensions}}{{^x-is-default}}
{{code}} => {{#dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}(github_response.to_json_async().await?)){{/dataType}}{{^dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}){{/dataType}},
{{code}} => {{#dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}(github_response.to_json_async().await?).into()){{/dataType}}{{^dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}.into()){{/dataType}},
{{/x-is-default}}{{/vendorExtensions}}{{/responses}}
code => Err({{classname}}{{operationIdCamelCase}}Error::Generic { code }),
code => Err({{classname}}{{operationIdCamelCase}}Error::Generic { code }.into()),
}
}
}
Expand All @@ -167,7 +174,7 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {
/// ---
#[cfg(not(target_arch = "wasm32"))]
{{#vendorExtensions.x-github.previews}}#[cfg(feature = "{{name}}")]
{{/vendorExtensions.x-github.previews}}pub fn {{operationId}}(&self{{#hasParams}}, {{/hasParams}}{{#pathParams}}{{paramName}}: {{#nullable}}Option<{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}>{{/nullable}}{{^nullable}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}{{/nullable}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{#hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}query_params: {{#vendorExtensions.x-codegen-has-optional-query-params}}Option<{{/vendorExtensions.x-codegen-has-optional-query-params}}impl Into<{{classname}}{{operationIdCamelCase}}Params{{#vendorExtensions.x-codegen-has-string-params}}<'api>{{/vendorExtensions.x-codegen-has-string-params}}>{{#vendorExtensions.x-codegen-has-optional-query-params}}>{{/vendorExtensions.x-codegen-has-optional-query-params}}{{#hasBodyParam}}, {{/hasBodyParam}}{{/hasQueryParams}}{{#hasBodyParam}}{{^hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}{{/hasQueryParams}}body: {{#bodyParam}}{{{dataType}}}{{/bodyParam}}{{/hasBodyParam}}) -> Result<{{#responses}}{{#vendorExtensions.x-is-default}}{{{dataType}}}{{/vendorExtensions.x-is-default}}{{/responses}}{{#vendorExtensions.x-codegen-response-empty-default}}(){{/vendorExtensions.x-codegen-response-empty-default}}, {{classname}}{{operationIdCamelCase}}Error> {
{{/vendorExtensions.x-github.previews}}pub fn {{operationId}}(&self{{#hasParams}}, {{/hasParams}}{{#pathParams}}{{paramName}}: {{#nullable}}Option<{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}>{{/nullable}}{{^nullable}}{{#isString}}&str{{/isString}}{{#isUuid}}&str{{/isUuid}}{{^isString}}{{^isUuid}}{{{dataType}}}{{/isUuid}}{{/isString}}{{/nullable}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{#hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}query_params: {{#vendorExtensions.x-codegen-has-optional-query-params}}Option<{{/vendorExtensions.x-codegen-has-optional-query-params}}impl Into<{{classname}}{{operationIdCamelCase}}Params{{#vendorExtensions.x-codegen-has-string-params}}<'api>{{/vendorExtensions.x-codegen-has-string-params}}>{{#vendorExtensions.x-codegen-has-optional-query-params}}>{{/vendorExtensions.x-codegen-has-optional-query-params}}{{#hasBodyParam}}, {{/hasBodyParam}}{{/hasQueryParams}}{{#hasBodyParam}}{{^hasQueryParams}}{{#hasPathParams}}, {{/hasPathParams}}{{/hasQueryParams}}body: {{#bodyParam}}{{{dataType}}}{{/bodyParam}}{{/hasBodyParam}}) -> Result<{{#responses}}{{#vendorExtensions.x-is-default}}{{{dataType}}}{{/vendorExtensions.x-is-default}}{{/responses}}{{#vendorExtensions.x-codegen-response-empty-default}}(){{/vendorExtensions.x-codegen-response-empty-default}}, AdapterError> {

let {{#hasQueryParams}}mut {{/hasQueryParams}}request_uri = format!("{}{{path}}", super::GITHUB_BASE_API_URL{{#hasPathParams}}, {{/hasPathParams}}{{#pathParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}});

Expand All @@ -188,12 +195,12 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {

let req = GitHubRequest {
uri: request_uri,
body: {{#hasBodyParam}}Some({{#bodyParam}}{{^vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-is-map-container}}HashMap{{/vendorExtensions.x-is-map-container}}{{^vendorExtensions.x-is-map-container}}{{{dataType}}}{{/vendorExtensions.x-is-map-container}}::from_json(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-codegen-body-bytes}}body.into(){{/vendorExtensions.x-codegen-body-bytes}}{{/bodyParam}}){{/hasBodyParam}}{{^hasBodyParam}}None{{/hasBodyParam}},
body: {{#hasBodyParam}}Some(C::from_json::<{{#bodyParam}}{{^vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-is-map-container}}HashMap{{/vendorExtensions.x-is-map-container}}{{^vendorExtensions.x-is-map-container}}{{{dataType}}}{{/vendorExtensions.x-is-map-container}}>(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{#vendorExtensions.x-codegen-body-bytes}}Vec<u8>>(body)?{{/vendorExtensions.x-codegen-body-bytes}}{{/bodyParam}}){{/hasBodyParam}}{{^hasBodyParam}}None{{/hasBodyParam}},
method: "{{httpMethod}}",
headers: vec![{{#vendorExtensions.x-github.previews}}("Accept", "application/vnd.github.{{name}}-preview+json"), {{/vendorExtensions.x-github.previews}}]
};

let request = GitHubRequestBuilder::build(req, self.client)?;
let request = self.client.build(req)?;

// --

Expand All @@ -206,9 +213,9 @@ impl<'api, C: Client<Req = crate::adapters::Req>> {{classname}}<'api, C> {
} else {
match github_response.status_code() {
{{#responses}}{{#vendorExtensions}}{{^x-is-default}}
{{code}} => {{#dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}(github_response.to_json()?)){{/dataType}}{{^dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}){{/dataType}},
{{code}} => {{#dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}(github_response.to_json()?).into()){{/dataType}}{{^dataType}}Err({{classname}}{{operationIdCamelCase}}Error::Status{{code}}.into()){{/dataType}},
{{/x-is-default}}{{/vendorExtensions}}{{/responses}}
code => Err({{classname}}{{operationIdCamelCase}}Error::Generic { code }),
code => Err({{classname}}{{operationIdCamelCase}}Error::Generic { code }.into()),
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion codegen/templates/lib.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@
//!
//! ```no_run
//! use roctogen::api::{self, repos};
//! use roctogen::adapters::client;
//! use roctogen::auth::Auth;
//!
//! let auth = Auth::None;
//! let client = client(&auth).expect("Cannot create new client");
//! let per_page = api::PerPage::new(10);
//!
//! let mut params: repos::ReposListCommitsParams = per_page.as_ref().into();
//! params = params.author("fussybeaver").page(2);
//!
//! repos::new(&auth).list_commits("fussybeaver", "bollard", Some(params));
//! repos::new(&client).list_commits("fussybeaver", "bollard", Some(params));
//! ```
//!
//! ## Async
Expand Down
Loading

0 comments on commit 9c11683

Please sign in to comment.