Skip to content

Commit

Permalink
Add kitsune-derive and use it throughout the project (#528)
Browse files Browse the repository at this point in the history
* implement kitsune-derive

* Use on every service

* remove startup figlet
  • Loading branch information
aumetra authored May 9, 2024
1 parent 8586d06 commit 03e8ca3
Show file tree
Hide file tree
Showing 44 changed files with 327 additions and 464 deletions.
333 changes: 60 additions & 273 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ members = [
"crates/kitsune-config",
"crates/kitsune-core",
"crates/kitsune-db",
"crates/kitsune-derive",
"crates/kitsune-derive/impl",
"crates/kitsune-email",
"crates/kitsune-embed",
"crates/kitsune-error",
Expand Down
14 changes: 14 additions & 0 deletions crates/kitsune-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "kitsune-derive"
authors.workspace = true
edition.workspace = true
version.workspace = true
license.workspace = true

[dependencies]
kitsune-derive-impl = { path = "impl" }
triomphe = "0.1.11"
typed-builder = "0.18.2"

[lints]
workspace = true
1 change: 1 addition & 0 deletions crates/kitsune-derive/LICENSE-AGPL-3.0
17 changes: 17 additions & 0 deletions crates/kitsune-derive/impl/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "kitsune-derive-impl"
authors.workspace = true
edition.workspace = true
version.workspace = true
license.workspace = true

[lib]
proc-macro = true

[dependencies]
proc-macro2 = "1.0.82"
quote = "1.0.36"
syn = { version = "2.0.61", features = ["full"] }

[lints]
workspace = true
116 changes: 116 additions & 0 deletions crates/kitsune-derive/impl/src/expand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::iter;
use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
spanned::Spanned,
Token, Visibility,
};

struct Attributes {
expand_builder: bool,
}

impl Default for Attributes {
fn default() -> Self {
Self {
expand_builder: true,
}
}
}

impl Parse for Attributes {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
let mut attributes = Self::default();
let punctuated = Punctuated::<syn::Ident, Token![,]>::parse_terminated(input)?;

for ident in punctuated {
if ident == "omit_builder" {
attributes.expand_builder = false;
} else {
return Err(syn::Error::new(
ident.span(),
format!("unknown attribute: {ident}"),
));
}
}

Ok(attributes)
}
}

fn expand_builder(
parsed_struct: &syn::ItemStruct,
inner_struct_name: &syn::Ident,
) -> (TokenStream, TokenStream) {
let struct_name = &parsed_struct.ident;
let inner_builder_name = format_ident!("{inner_struct_name}Builder");

let num_lifetimes = parsed_struct.generics.lifetimes().count();
let lifetimes = iter::repeat(quote!('_)).take(num_lifetimes);

let attrs = quote! {
#[derive(::kitsune_derive::typed_builder::TypedBuilder)]
#[builder(build_method(into = #struct_name))]
#[builder(crate_module_path = ::kitsune_derive::typed_builder)]
};
let impls = quote! {
impl #struct_name {
pub fn builder() -> #inner_builder_name<#(#lifetimes),*> {
#inner_struct_name::builder()
}
}
};

(attrs, impls)
}

pub fn expand(attrs: TokenStream, input: TokenStream) -> syn::Result<TokenStream> {
let attributes = syn::parse2::<Attributes>(attrs)?;
let mut parsed_struct = syn::parse2::<syn::ItemStruct>(input)?;

let struct_name = parsed_struct.ident.clone();
let inner_struct_name = format_ident!("__{struct_name}__Inner");

let (builder_attrs, builder_impls) = if attributes.expand_builder {
expand_builder(&parsed_struct, &inner_struct_name)
} else {
(TokenStream::new(), TokenStream::new())
};

parsed_struct.ident = inner_struct_name.clone();
parsed_struct.vis = Visibility::Public(Token![pub](parsed_struct.span()));

let output = quote! {
#builder_attrs
#[allow(non_camel_case_types)]
#[doc(hidden)]
#parsed_struct

#[derive(Clone)]
pub struct #struct_name {
inner: ::kitsune_derive::triomphe::Arc<#inner_struct_name>,
}

#builder_impls

impl ::core::ops::Deref for #struct_name {
type Target = #inner_struct_name;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl From<#inner_struct_name> for #struct_name {
fn from(inner: #inner_struct_name) -> Self {
Self {
inner: ::kitsune_derive::triomphe::Arc::new(inner),
}
}
}
};

Ok(output)
}
12 changes: 12 additions & 0 deletions crates/kitsune-derive/impl/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod expand;

#[proc_macro_attribute]
pub fn kitsune_service(
attrs: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
match self::expand::expand(attrs.into(), input.into()) {
Ok(out) => out.into(),
Err(error) => error.to_compile_error().into(),
}
}
3 changes: 3 additions & 0 deletions crates/kitsune-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub use ::kitsune_derive_impl::kitsune_service;
pub use ::triomphe;
pub use ::typed_builder;
2 changes: 1 addition & 1 deletion crates/kitsune-embed/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ embed-sdk = { git = "https://github.com/Lantern-chat/embed-service.git", rev = "
http = "1.1.0"
iso8601-timestamp = "0.2.17"
kitsune-db = { path = "../kitsune-db" }
kitsune-derive = { path = "../kitsune-derive" }
kitsune-error = { path = "../kitsune-error" }
kitsune-http-client = { path = "../kitsune-http-client" }
once_cell = "1.19.0"
scraper = { version = "0.19.0", default-features = false }
smol_str = "0.2.1"
typed-builder = "0.18.2"

[lints]
workspace = true
4 changes: 2 additions & 2 deletions crates/kitsune-embed/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ use kitsune_db::{
schema::link_previews,
with_connection, PgPool,
};
use kitsune_derive::kitsune_service;
use kitsune_error::Result;
use kitsune_http_client::Client as HttpClient;
use once_cell::sync::Lazy;
use scraper::{Html, Selector};
use smol_str::SmolStr;
use typed_builder::TypedBuilder;

pub use embed_sdk;
pub use embed_sdk::Embed;
Expand All @@ -32,7 +32,7 @@ fn first_link_from_fragment(fragment: &str) -> Option<String> {
.and_then(|element| element.value().attr("href").map(ToString::to_string))
}

#[derive(Clone, TypedBuilder)]
#[kitsune_service]
pub struct Client {
db_pool: PgPool,
#[builder(setter(into))]
Expand Down
1 change: 1 addition & 0 deletions crates/kitsune-federation-filter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ license.workspace = true
[dependencies]
globset = "0.4.14"
kitsune-config = { path = "../kitsune-config" }
kitsune-derive = { path = "../kitsune-derive" }
kitsune-error = { path = "../kitsune-error" }
kitsune-type = { path = "../kitsune-type" }
url = "2.5.0"
Expand Down
13 changes: 8 additions & 5 deletions crates/kitsune-federation-filter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use globset::{Glob, GlobSet, GlobSetBuilder};
use kitsune_config::instance::FederationFilterConfiguration;
use kitsune_derive::kitsune_service;
use kitsune_error::{kitsune_error, Result};
use kitsune_type::ap::{actor::Actor, Activity, Object};
use std::sync::Arc;
use url::Url;

pub trait Entity {
Expand Down Expand Up @@ -33,9 +33,9 @@ enum FilterMode {
Deny,
}

#[derive(Clone)]
#[kitsune_service(omit_builder)]
pub struct FederationFilter {
domains: Arc<GlobSet>,
domains: GlobSet,
filter: FilterMode,
}

Expand All @@ -50,9 +50,12 @@ impl FederationFilter {
for glob in globs {
globset.add(Glob::new(glob)?);
}
let domains = Arc::new(globset.build()?);

Ok(Self { domains, filter })
Ok(__FederationFilter__Inner {
domains: globset.build()?,
filter,
}
.into())
}

pub fn is_url_allowed(&self, url: &Url) -> Result<bool> {
Expand Down
1 change: 1 addition & 0 deletions crates/kitsune-oidc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum_dispatch = "0.3.13"
http = "1.1.0"
http-body-util = "0.1.1"
kitsune-config = { path = "../kitsune-config" }
kitsune-derive = { path = "../kitsune-derive" }
kitsune-error = { path = "../kitsune-error" }
kitsune-http-client = { path = "../kitsune-http-client" }
moka = { version = "0.12.7", features = ["future"] }
Expand Down
8 changes: 5 additions & 3 deletions crates/kitsune-oidc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::state::{
LoginState, OAuth2LoginState, Store,
};
use kitsune_config::oidc::{Configuration, StoreConfiguration};
use kitsune_derive::kitsune_service;
use kitsune_error::{bail, kitsune_error, Result};
use multiplex_pool::RoundRobinStrategy;
use openidconnect::{
Expand Down Expand Up @@ -66,7 +67,7 @@ pub struct UserInfo {
pub oauth2: OAuth2Info,
}

#[derive(Clone)]
#[kitsune_service(omit_builder)]
pub struct OidcService {
client: OidcClient,
login_state_store: self::state::AnyStore,
Expand Down Expand Up @@ -103,10 +104,11 @@ impl OidcService {
}
};

Ok(Self {
Ok(__OidcService__Inner {
client,
login_state_store,
})
}
.into())
}

pub async fn authorisation_url(
Expand Down
2 changes: 1 addition & 1 deletion crates/kitsune-search/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ futures-util = "0.3.30"
http = "1.1.0"
kitsune-config = { path = "../kitsune-config" }
kitsune-db = { path = "../kitsune-db" }
kitsune-derive = { path = "../kitsune-derive" }
kitsune-error = { path = "../kitsune-error" }
kitsune-http-client = { path = "../kitsune-http-client" }
kitsune-language = { path = "../kitsune-language" }
Expand All @@ -27,7 +28,6 @@ serde_urlencoded = "0.7.1"
speedy-uuid = { path = "../../lib/speedy-uuid" }
strum = { version = "0.26.2", features = ["derive"] }
tracing = "0.1.40"
typed-builder = "0.18.2"

[lints]
workspace = true
7 changes: 4 additions & 3 deletions crates/kitsune-search/src/meilisearch/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use self::http_client::HttpClient;
use super::{Result, SearchBackend, SearchIndex, SearchItem, SearchResultReference};
use kitsune_derive::kitsune_service;
use meilisearch_sdk::{client::Client, indexes::Index, settings::Settings};
use serde::Deserialize;
use speedy_uuid::Uuid;
Expand All @@ -12,7 +13,7 @@ struct MeilisearchResult {
id: Uuid,
}

#[derive(Clone)]
#[kitsune_service(omit_builder)]
pub struct MeiliSearchService {
client: Client<HttpClient>,
}
Expand All @@ -29,9 +30,9 @@ impl MeiliSearchService {
.content_length_limit(None)
.build(),
};
let service = Self {
let service = Self::from(__MeiliSearchService__Inner {
client: Client::new_with_client(host, Some(api_key), http_client),
};
});

let settings = Settings::new()
.with_filterable_attributes(["created_at"])
Expand Down
4 changes: 2 additions & 2 deletions crates/kitsune-search/src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ use kitsune_db::{
schema::{accounts, posts},
with_connection, PgPool,
};
use kitsune_derive::kitsune_service;
use speedy_uuid::Uuid;
use typed_builder::TypedBuilder;

#[derive(Clone, TypedBuilder)]
#[kitsune_service]
pub struct SearchService {
db_pool: PgPool,
language_detection_config: LanguageDetectionConfig,
Expand Down
1 change: 1 addition & 0 deletions crates/kitsune-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ kitsune-captcha = { path = "../kitsune-captcha" }
kitsune-config = { path = "../kitsune-config" }
kitsune-core = { path = "../kitsune-core" }
kitsune-db = { path = "../kitsune-db" }
kitsune-derive = { path = "../kitsune-derive" }
kitsune-email = { path = "../kitsune-email" }
kitsune-embed = { path = "../kitsune-embed" }
kitsune-error = { path = "../kitsune-error" }
Expand Down
3 changes: 2 additions & 1 deletion crates/kitsune-service/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use kitsune_db::{
schema::{accounts, accounts_follows, accounts_preferences, notifications, posts},
with_connection, PgPool,
};
use kitsune_derive::kitsune_service;
use kitsune_error::{Error, Result};
use kitsune_jobs::deliver::{
accept::DeliverAccept,
Expand Down Expand Up @@ -178,7 +179,7 @@ impl<A, H> Update<A, H> {
}
}

#[derive(Clone, TypedBuilder)]
#[kitsune_service]
pub struct AccountService {
attachment_service: AttachmentService,
db_pool: PgPool,
Expand Down
3 changes: 2 additions & 1 deletion crates/kitsune-service/src/attachment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use kitsune_db::{
schema::media_attachments,
with_connection, PgPool,
};
use kitsune_derive::kitsune_service;
use kitsune_error::{kitsune_error, Error, ErrorType, Result};
use kitsune_http_client::Client;
use kitsune_storage::{AnyStorageBackend, StorageBackend};
Expand Down Expand Up @@ -73,7 +74,7 @@ impl<S> Upload<S> {
}
}

#[derive(Clone, TypedBuilder)]
#[kitsune_service]
pub struct AttachmentService {
#[builder(default =
Client::builder()
Expand Down
Loading

0 comments on commit 03e8ca3

Please sign in to comment.