Skip to content

Commit

Permalink
Merge pull request #123 from ngyn-rs/dev
Browse files Browse the repository at this point in the history
v0.4.1 - Injection fixes
  • Loading branch information
elcharitas authored Jul 7, 2024
2 parents a55880b + 984daab commit b9a14eb
Show file tree
Hide file tree
Showing 18 changed files with 340 additions and 1,457 deletions.
1,613 changes: 245 additions & 1,368 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.4.0"
edition = "2021"
description = "Modular backend framework for web applications"
license = "MIT"
rust-version = "1.63"

[lib]
path = "src/lib.rs"
Expand Down
38 changes: 16 additions & 22 deletions crates/macros/src/common/controller_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt

let controller_fields = parse_macro_data(data);

let mut add_fields = Vec::new();
let mut inject_fields = Vec::new();
let fields: Vec<_> = controller_fields
.iter()
.map(
Expand All @@ -123,27 +125,17 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
colon_token,
..
}| {
quote! {
#(#attrs),* #vis #ident #colon_token #ty
add_fields.push(quote! {
#ident #colon_token #ty::default()
});
if attrs.iter().any(|attr| attr.path().is_ident("inject")) {
inject_fields.push(quote! {
self.#ident.inject(cx);
});
}
},
)
.collect();

let add_fields: Vec<_> = controller_fields
.iter()
.map(
|syn::Field {
ident,
ty,
colon_token,
attrs,
vis,
..
}| {
let attrs = attrs.iter().filter(|attr| !attr.path().is_ident("inject"));
quote! {
#(#attrs),*
#vis #ident #colon_token #ty::default()
#(#attrs),* #vis #ident #colon_token #ty
}
},
)
Expand All @@ -153,7 +145,7 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
.iter()
.map(|m| {
quote! {
let middleware = #m::default();
let mut middleware = #m::default();
middleware.inject(cx);
middleware.handle(cx, res);
}
Expand Down Expand Up @@ -211,7 +203,7 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
#init_controller
}

fn inject(&self, cx: &ngyn::prelude::NgynContext) {
fn inject(&mut self, cx: &ngyn::prelude::NgynContext) {
#inject_controller
}
}
Expand All @@ -225,10 +217,12 @@ pub(crate) fn controller_macro(args: TokenStream, input: TokenStream) -> TokenSt
}

async fn handle(
&self, handler: &str,
&mut self,
handler: &str,
cx: &mut ngyn::prelude::NgynContext,
res: &mut ngyn::prelude::NgynResponse,
) {
#(#inject_fields)*
#(#add_middlewares)*
self.__handle_route(handler, cx, res).await;
}
Expand Down
5 changes: 5 additions & 0 deletions crates/macros/src/common/inject_macro.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use proc_macro::TokenStream;

pub(crate) fn inject_macro(_args: TokenStream, raw_input: TokenStream) -> TokenStream {
raw_input
}
33 changes: 13 additions & 20 deletions crates/macros/src/common/injectable_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
quote! {}
};

let mut add_fields = Vec::new();
let mut inject_fields = Vec::new();
let fields: Vec<_> = injectable_fields
.iter()
.map(
Expand All @@ -75,27 +77,17 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
colon_token,
..
}| {
quote! {
#(#attrs),* #vis #ident #colon_token #ty
add_fields.push(quote! {
#ident #colon_token #ty::default()
});
if attrs.iter().any(|attr| attr.path().is_ident("inject")) {
inject_fields.push(quote! {
self.#ident.inject(cx);
});
}
},
)
.collect();

let add_fields: Vec<_> = injectable_fields
.iter()
.map(
|syn::Field {
ident,
ty,
colon_token,
attrs,
vis,
..
}| {
let attrs = attrs.iter().filter(|attr| !attr.path().is_ident("inject"));
quote! {
#(#attrs),*
#vis #ident #colon_token #ty::default()
#(#attrs),* #vis #ident #colon_token #ty
}
},
)
Expand Down Expand Up @@ -136,7 +128,8 @@ pub(crate) fn injectable_macro(args: TokenStream, input: TokenStream) -> TokenSt
#init_injectable
}

fn inject(&self, cx: &ngyn::prelude::NgynContext) {
fn inject(&mut self, cx: &ngyn::prelude::NgynContext) {
#(#inject_fields)*
#inject_injectable
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/macros/src/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod check_macro;
pub mod controller_macro;
pub mod inject_macro;
pub mod injectable_macro;
pub mod route_macro;
pub mod routes_macro;
2 changes: 1 addition & 1 deletion crates/macros/src/common/routes_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub(crate) fn routes_macro(raw_input: TokenStream) -> TokenStream {
#gates
{
use ngyn::prelude::NgynGate;
let gate = #path::default();
let mut gate = #path::default();
gate.inject(cx);
if !gate.can_activate(cx, res) {
return;
Expand Down
27 changes: 8 additions & 19 deletions crates/macros/src/core/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub(crate) fn module_macro(args: TokenStream, input: TokenStream) -> TokenStream
let args = parse_macro_input!(args as ModuleArgs);
let module_fields = parse_macro_data(data);

let mut add_fields = Vec::new();
let fields: Vec<_> = module_fields
.iter()
.map(
Expand All @@ -77,36 +78,24 @@ pub(crate) fn module_macro(args: TokenStream, input: TokenStream) -> TokenStream
colon_token,
..
}| {
add_fields.push(quote! {
#ident #colon_token #ty::default()
});
let attrs = attrs.iter().filter(|attr| !attr.path().is_ident("inject"));
quote! {
#(#attrs),* #vis #ident #colon_token #ty
}
},
)
.collect();

let add_fields: Vec<_> = module_fields
.iter()
.map(
|syn::Field {
ident,
ty,
colon_token,
..
}| {
quote! {
#ident #colon_token #ty::default()
}
},
)
.collect();

let add_controllers: Vec<_> = args
.controllers
.iter()
.map(|controller| {
quote! {
let controller: #controller = #controller::new();
controllers.push(std::sync::Arc::new(controller));
controllers.push(std::sync::Arc::new(std::sync::Mutex::new(vec![Box::new(controller)])));
}
})
.collect();
Expand Down Expand Up @@ -151,10 +140,10 @@ pub(crate) fn module_macro(args: TokenStream, input: TokenStream) -> TokenStream
fn name(&self) -> &str {
stringify!(#ident)
}
fn get_controllers(&mut self) -> Vec<std::sync::Arc<dyn ngyn::shared::traits::NgynController>> {
fn get_controllers(&mut self) -> Vec<std::sync::Arc<std::sync::Mutex<Vec<Box<dyn ngyn::shared::traits::NgynController>>>>> {
use ngyn::shared::traits::NgynInjectable;
let mut modules: Vec<std::sync::Arc<dyn ngyn::shared::traits::NgynModule>> = vec![];
let mut controllers: Vec<std::sync::Arc<dyn ngyn::shared::traits::NgynController>> = vec![];
let mut controllers: Vec<std::sync::Arc<std::sync::Mutex<Vec<Box<dyn ngyn::shared::traits::NgynController>>>>> = vec![];
#(#add_controllers)*
#(#add_imported_modules_controllers)*
controllers
Expand Down
8 changes: 8 additions & 0 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::common::{controller_macro::*, injectable_macro::*, route_macro::*, ro
use crate::core::dto::dto_macro;
use crate::core::module::*;
use common::check_macro::check_impl_macro;
use common::inject_macro::inject_macro;
use proc_macro::TokenStream;

#[proc_macro_attribute]
Expand Down Expand Up @@ -63,6 +64,13 @@ pub fn injectable(args: TokenStream, input: TokenStream) -> TokenStream {
injectable_macro(args, input)
}

#[proc_macro_attribute]
/// The `inject` attribute is used to mark a field as injectable.
/// The field must be a struct that is marked with the `injectable` attribute.
pub fn inject(args: TokenStream, input: TokenStream) -> TokenStream {
inject_macro(args, input)
}

#[proc_macro_attribute]
/// The `controller` attribute is used to mark a struct as a controller.
///
Expand Down
8 changes: 7 additions & 1 deletion crates/shared/src/core/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,13 @@ pub trait NgynEngine: NgynPlatform {
let mut module = AppModule::new();
let mut server = Self::default();
for controller in module.get_controllers() {
for (path, http_method, handler) in controller.routes() {
let routes = controller
.lock()
.unwrap()
.iter()
.flat_map(|c| c.routes())
.collect::<Vec<_>>();
for (path, http_method, handler) in routes {
server.route(
path.as_str(),
Method::from_bytes(http_method.to_uppercase().as_bytes()).unwrap(),
Expand Down
17 changes: 12 additions & 5 deletions crates/shared/src/server/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

use hyper::Request;
use serde::{Deserialize, Serialize};
use std::{any::Any, collections::HashMap, sync::Arc};
use std::{any::Any, collections::HashMap};

use crate::{
server::{uri::ToParams, Method, NgynRequest, NgynResponse, Transformer},
traits::NgynController,
traits::ControllerList,
};

/// Represents the value of a context in Ngyn
Expand Down Expand Up @@ -43,7 +43,7 @@ impl<T: Send + Sync + 'static> AppState for T {
pub struct NgynContext {
request: Request<Vec<u8>>,
params: Option<Vec<(String, String)>>,
route_info: Option<(String, Arc<dyn NgynController>)>,
route_info: Option<(String, ControllerList)>,
store: HashMap<String, String>,
state: Option<Box<dyn AppState>>,
}
Expand Down Expand Up @@ -391,7 +391,7 @@ impl NgynContext {
///
/// context.prepare(Arc::new(controller), "index".to_string());
/// ```
pub(crate) fn prepare(&mut self, controller: Arc<dyn NgynController>, handler: String) {
pub(crate) fn prepare(&mut self, controller: ControllerList, handler: String) {
self.route_info = Some((handler, controller));
}

Expand All @@ -413,7 +413,14 @@ impl NgynContext {
/// context.execute(&mut response).await;
/// ```
pub(crate) async fn execute(&mut self, res: &mut NgynResponse) {
if let Some((handler, controller)) = self.route_info.clone() {
let route = self.route_info.as_mut().map(|(handle, controller_arc)| {
(
handle.clone(),
controller_arc.clone().lock().unwrap().pop().unwrap(),
)
});

if let Some((handler, mut controller)) = route {
controller.inject(self);
controller.handle(handler.as_str(), self, res).await;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/shared/src/traits/controller_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ pub trait NgynController: NgynInjectable + Sync {

/// This is for internal use only. It handles the routing logic of the controller.
async fn handle(
&self,
&mut self,
handler: &str,
cx: &mut crate::server::NgynContext,
res: &mut crate::server::NgynResponse,
Expand Down
2 changes: 1 addition & 1 deletion crates/shared/src/traits/injectable_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ pub trait NgynInjectable: Send {
where
Self: Sized;

fn inject(&self, _cx: &NgynContext) {}
fn inject(&mut self, _cx: &NgynContext) {}
}
6 changes: 5 additions & 1 deletion crates/shared/src/traits/module_trait.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::sync::{Arc, Mutex};

use crate::traits::NgynController;

pub(crate) type ControllerList = Arc<Mutex<Vec<Box<dyn NgynController>>>>;

/// `NgynModule` is a trait that defines the basic structure of a module in Ngyn.
pub trait NgynModule: Send {
/// Creates a new instance of the module.
Expand All @@ -11,5 +15,5 @@ pub trait NgynModule: Send {
fn name(&self) -> &str;

/// Returns the controllers of the module.
fn get_controllers(&mut self) -> Vec<std::sync::Arc<dyn NgynController>>;
fn get_controllers(&mut self) -> Vec<ControllerList>;
}
5 changes: 3 additions & 2 deletions examples/basic_app/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ edition = "2021"

[dependencies]
async-std = { version = "1.6.0", features = ["attributes"] }
nject = "0.3.0"
ngyn = { version = "0.3.1", features = ["tide"] }
ngyn = { version = "0.4.0" }
ngyn-hyper = { version = "0.1.0" }
tokio = { version = "1", features = ["full"] }
18 changes: 7 additions & 11 deletions examples/basic_app/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
mod modules;

use modules::sample::sample_module::SampleModule;
use ngyn::{
platforms::{NgynApplication, Result},
prelude::*,
};
use ngyn::prelude::*;
use ngyn_hyper::HyperApplication;

#[ngyn::macros::main]
async fn main() -> Result<()> {
let mut app = NgynFactory::<NgynApplication>::create::<SampleModule>();
#[tokio::main]
async fn main() {
let mut app = NgynFactory::<HyperApplication>::create::<SampleModule>();

app.get(
"/author",
|_req: &mut NgynRequest, res: &mut NgynResponse| {
|_cx: &mut NgynContext, res: &mut NgynResponse| {
res.send("Ngyn is created by @elcharitas.");
},
);

println!("Starting server at http://127.0.0.1:8080");

app.listen("0.0.0.0:8080").await?;

Ok(())
let _ = app.listen("0.0.0.0:8080").await;
}
Loading

0 comments on commit b9a14eb

Please sign in to comment.