diff --git a/generator/src/_Cargo.toml b/generator/src/_Cargo.toml index 82d1d298..783d5de1 100644 --- a/generator/src/_Cargo.toml +++ b/generator/src/_Cargo.toml @@ -15,6 +15,7 @@ seaography = { path = "../../" } # TODO before production place version here tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread"] } tracing = { version = "0.1.34" } tracing-subscriber = { version = "0.3.11" } +dotenv = "0.15.0" [dev-dependencies] serde_json = { version = '1.0.82' } diff --git a/generator/src/lib.rs b/generator/src/lib.rs index ab9379f9..9b313bfc 100644 --- a/generator/src/lib.rs +++ b/generator/src/lib.rs @@ -72,6 +72,8 @@ pub async fn write_project>( db_url: &str, crate_name: &str, expanded_format: bool, + depth_limit: Option, + complexity_limit: Option, ) -> Result<()> { let database_url = parse_database_url(db_url)?; @@ -92,7 +94,8 @@ pub async fn write_project>( writer::write_query_root(src_path, &entities_hashmap).unwrap(); writer::write_lib(src_path)?; - writer::write_main(src_path, db_url, crate_name)?; + writer::write_main(src_path, crate_name)?; + writer::write_env(&path.as_ref(), db_url, depth_limit, complexity_limit)?; sea_orm_codegen::write_entities(&src_path.join("entities"), entities_hashmap.clone()).unwrap(); diff --git a/generator/src/writer.rs b/generator/src/writer.rs index 0e0fc07c..977c103d 100644 --- a/generator/src/writer.rs +++ b/generator/src/writer.rs @@ -95,17 +95,20 @@ pub fn write_lib>(path: &P) -> std::io::Result<()> { /// /// Used to generate project/src/main.rs file content /// -pub fn generate_main(db_url: &str, crate_name: &str) -> TokenStream { +pub fn generate_main(crate_name: &str) -> TokenStream { let crate_name_token: TokenStream = crate_name.parse().unwrap(); quote! { use async_graphql::{ + dataloader::DataLoader, http::{playground_source, GraphQLPlaygroundConfig}, - EmptyMutation, EmptySubscription, Schema, dataloader::DataLoader + EmptyMutation, EmptySubscription, Schema, }; use async_graphql_poem::GraphQL; + use dotenv::dotenv; use poem::{get, handler, listener::TcpListener, web::Html, IntoResponse, Route, Server}; use sea_orm::Database; + use std::env; use #crate_name_token::*; @@ -113,34 +116,54 @@ pub fn generate_main(db_url: &str, crate_name: &str) -> TokenStream { async fn graphql_playground() -> impl IntoResponse { Html(playground_source(GraphQLPlaygroundConfig::new("/"))) } - #[tokio::main] async fn main() { + dotenv().ok(); + + let db_url = env::var("DATABASE_URL").expect("DATABASE_URL environment variable not set"); + + let depth_limit = env::var("DEPTH_LIMIT") + .map(|data| data.parse::().expect("DEPTH_LIMIT is not a number")) + .map_or(None, |data| Some(data)); + + let complexity_limit = env::var("COMPLEXITY_LIMIT") + .map(|data| { + data.parse::() + .expect("COMPLEXITY_LIMIT is not a number") + }) + .map_or(None, |data| Some(data)); + tracing_subscriber::fmt() .with_max_level(tracing::Level::DEBUG) .with_test_writer() .init(); - - // TODO: use .env file to configure url - let database = Database::connect(#db_url).await.unwrap(); - - // TODO use environment variables to configure dataloader batch size + let database = Database::connect(db_url).await.unwrap(); let orm_dataloader: DataLoader = DataLoader::new( OrmDataloader { - db: database.clone() + db: database.clone(), }, - tokio::spawn - ) ; - + tokio::spawn, + ); let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription) .data(database) - .data(orm_dataloader) - .finish(); + .data(orm_dataloader); - let app = Route::new().at("/", get(graphql_playground).post(GraphQL::new(schema))); + let schema = if let Some(depth) = depth_limit { + schema.limit_depth(depth) + } else { + schema + }; - println!("Playground: http://localhost:8000"); + let schema = if let Some(complexity) = complexity_limit { + schema.limit_complexity(complexity) + } else { + schema + }; + let schema = schema.finish(); + + let app = Route::new().at("/", get(graphql_playground).post(GraphQL::new(schema))); + println!("Playground: http://localhost:8000"); Server::new(TcpListener::bind("0.0.0.0:8000")) .run(app) .await @@ -152,10 +175,9 @@ pub fn generate_main(db_url: &str, crate_name: &str) -> TokenStream { pub fn write_main>( path: &P, - db_url: &str, crate_name: &str, ) -> std::io::Result<()> { - let tokens = generate_main(db_url, crate_name); + let tokens = generate_main(crate_name); let file_name = path.as_ref().join("main.rs"); @@ -163,3 +185,25 @@ pub fn write_main>( Ok(()) } + +pub fn write_env>( + path: &P, + db_url: &str, + depth_limit: Option, + complexity_limit: Option, +) -> std::io::Result<()> { + let depth_limit = depth_limit.map_or("".into(), |value| value.to_string()); + let complexity_limit = complexity_limit.map_or("".into(), |value| value.to_string()); + + let tokens = format!(r#" + DATABASE_URL="{db_url}" + # COMPLEXITY_LIMIT={depth_limit} + # DEPTH_LIMIT={complexity_limit} + "#); + + let file_name = path.as_ref().join(".env"); + + std::fs::write(file_name, tokens.to_string())?; + + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 4b3bd5b3..c5ffb6a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,15 @@ pub struct Args { #[clap(value_parser)] pub destination: String, + + #[clap(short, long)] + pub expanded_format: Option, + + #[clap(short, long)] + pub depth_limit: Option, + + #[clap(short, long)] + pub complexity_limit: Option, } #[derive(Debug, Clone, Copy, PartialEq, Eq, async_graphql::Enum)] diff --git a/src/main.rs b/src/main.rs index 1a49a8db..ccc35850 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,11 +7,14 @@ async fn main() { let path = std::path::Path::new(&args.destination); - let expanded_format = false; - - let db_url = &args.database_url; - - write_project(&path, db_url, &args.crate_name, expanded_format) + write_project( + &path, + &args.database_url, + &args.crate_name, + args.expanded_format.unwrap_or(false), + args.depth_limit, + args.complexity_limit + ) .await .unwrap(); }