diff --git a/Cargo.lock b/Cargo.lock index 3e90c05..c8b3587 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,12 +165,13 @@ dependencies = [ [[package]] name = "dagger-rs" -version = "0.1.1" +version = "0.1.2" dependencies = [ "clap", "dirs", "eyre", "flate2", + "genco", "graphql-introspection-query", "graphql_client", "hex", @@ -383,6 +384,28 @@ dependencies = [ "slab", ] +[[package]] +name = "genco" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43de41c8ce1ed5ac84a1b11fb3e4ef604bf6773068798490eaa95e8151abad20" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85fd34848b1f708e6344a4af6f7bfc05172ae20ce4b35c8e417efffb4f306aa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "generic-array" version = "0.14.6" @@ -892,6 +915,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "relative-path" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3bf6b372449361333ac1f498b7edae4dd5e70dccd7c0c2a7c7bce8f05ede648" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1056,6 +1085,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + [[package]] name = "socket2" version = "0.4.7" diff --git a/Cargo.toml b/Cargo.toml index 12f368e..f4df823 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ clap = "4.1.4" dirs = "4.0.0" eyre = "0.6.8" flate2 = { version = "1.0.25", features = ["zlib"] } +genco = "0.17.3" graphql-introspection-query = "0.2.0" graphql_client = { version = "0.12.0", features = [ "reqwest", diff --git a/crates/dagger-codegen/Cargo.lock b/crates/dagger-codegen/Cargo.lock new file mode 100644 index 0000000..3a12015 --- /dev/null +++ b/crates/dagger-codegen/Cargo.lock @@ -0,0 +1,157 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "dagger-codegen" +version = "0.1.0" +dependencies = [ + "eyre", + "genco", + "graphql-introspection-query", + "serde", + "serde_json", +] + +[[package]] +name = "eyre" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "genco" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43de41c8ce1ed5ac84a1b11fb3e4ef604bf6773068798490eaa95e8151abad20" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85fd34848b1f708e6344a4af6f7bfc05172ae20ce4b35c8e417efffb4f306aa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "graphql-introspection-query" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d" +dependencies = [ + "serde", +] + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "proc-macro2" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "relative-path" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3bf6b372449361333ac1f498b7edae4dd5e70dccd7c0c2a7c7bce8f05ede648" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" diff --git a/crates/dagger-codegen/Cargo.toml b/crates/dagger-codegen/Cargo.toml new file mode 100644 index 0000000..49ae920 --- /dev/null +++ b/crates/dagger-codegen/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "dagger-codegen" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +eyre = "0.6.8" +genco = "0.17.3" +graphql-introspection-query = "0.2.0" +serde = { version = "1.0.152", features = ["derive"] } +serde_json = "1.0.91" diff --git a/crates/dagger-codegen/src/codegen.rs b/crates/dagger-codegen/src/codegen.rs new file mode 100644 index 0000000..765a367 --- /dev/null +++ b/crates/dagger-codegen/src/codegen.rs @@ -0,0 +1,89 @@ +use graphql_introspection_query::introspection_response::{ + FullType, IntrospectionResponse, Schema, +}; + +use crate::{ + handlers::{DynHandler, Handlers}, + predicates::is_custom_scalar_type, +}; + +#[allow(dead_code)] +pub struct CodeGeneration { + handlers: Handlers, +} + +impl CodeGeneration { + pub fn new() -> Self { + Self { handlers: vec![] } + } + + pub fn generate(&self, schema: &IntrospectionResponse) -> eyre::Result { + let code = self.generate_from_schema( + schema + .as_schema() + .schema + .as_ref() + .ok_or(eyre::anyhow!("could not get schema to generate code from"))?, + )?; + Ok(code) + } + + fn generate_from_schema(&self, schema: &Schema) -> eyre::Result { + let mut output = String::new(); + output.push_str("# code generated by dagger. DO NOT EDIT."); + + let types = get_types(schema)?; + //let remaining: Vec> = types.into_iter().map(type_name).collect(); + + todo!() + } + + pub fn type_name(&self, t: &FullType) -> Option { + let name = t.name.as_ref(); + if let Some(name) = name { + if name.starts_with("_") || !is_custom_scalar_type(t) { + return None; + } + + return Some(name.replace("Query", "Client")); + } + + None + } + + fn group_key(&self, t: &FullType) -> Option { + for handler in self.handlers.iter() { + if handler.predicate(&t) { + return Some(handler.clone()); + } + } + + None + } + + fn sort_key(&self, t: &FullType) -> (isize, String) { + for (i, handler) in self.handlers.iter().enumerate() { + if handler.predicate(t) { + return (i as isize, t.name.as_ref().unwrap().clone()); + } + } + + return (-1, t.name.as_ref().unwrap().clone()); + } +} + +fn get_types(schema: &Schema) -> eyre::Result> { + let types = schema + .types + .as_ref() + .ok_or(eyre::anyhow!("types not found on schema"))?; + + // 1. Get a list of all types and map it to handlers + let types: Vec<&FullType> = types + .iter() + .map(|t| t.as_ref().map(|t| &t.full_type)) + .flatten() + .collect(); + + Ok(types) +} diff --git a/crates/dagger-codegen/src/handlers/mod.rs b/crates/dagger-codegen/src/handlers/mod.rs new file mode 100644 index 0000000..09588f5 --- /dev/null +++ b/crates/dagger-codegen/src/handlers/mod.rs @@ -0,0 +1,82 @@ +use std::sync::Arc; + +use genco::prelude::rust::Tokens; +use genco::prelude::*; +use graphql_introspection_query::introspection_response::FullType; + +pub trait Handler { + fn predicate(&self, t: &FullType) -> bool { + false + } + + fn render(&self, t: &FullType) -> eyre::Result { + let mut s = String::new(); + + s.push_str("\n"); + s.push_str(self.render_struct(t)?.to_string()?.as_str()); + s.push_str("\n"); + s.push_str(self.render_impl(t)?.to_string()?.as_str()); + s.push_str("\n"); + + Ok(s) + } + + fn render_struct(&self, t: &FullType) -> eyre::Result { + let name = t.name.as_ref().ok_or(eyre::anyhow!("name not found"))?; + + Ok(quote! { + pub $name {} { + // TODO: Add fields + } + }) + } + + fn render_impl(&self, t: &FullType) -> eyre::Result { + let name = t.name.as_ref().ok_or(eyre::anyhow!("name not found"))?; + + Ok(quote! { + pub $name {} { + // TODO: Add fields + } + }) + } +} + +pub type DynHandler = Arc; +pub type Handlers = Vec; + +#[cfg(test)] +mod tests { + use graphql_introspection_query::introspection_response::FullType; + + use super::Handler; + + struct DefaultHandler; + impl Handler for DefaultHandler {} + + #[test] + fn render_returns_expected() { + let handler = DefaultHandler {}; + let t = FullType { + kind: None, + name: Some("SomeName".into()), + description: None, + fields: None, + input_fields: None, + interfaces: None, + enum_values: None, + possible_types: None, + }; + + let res = handler.render(&t).unwrap(); + + assert_eq!( + res, + " +pub SomeName {} { } +pub SomeName {} { } +" + .to_string() + ); + } +} diff --git a/src/code_generation.rs b/crates/dagger-codegen/src/lib.rs similarity index 98% rename from src/code_generation.rs rename to crates/dagger-codegen/src/lib.rs index 359ac0a..7038844 100644 --- a/src/code_generation.rs +++ b/crates/dagger-codegen/src/lib.rs @@ -1,109 +1,18 @@ -use graphql_introspection_query::introspection_response::{ - self, FullType, IntrospectionResponse, Schema, SchemaTypes, -}; - -pub struct CodeGeneration; - -impl CodeGeneration { - pub fn generate(schema: &IntrospectionResponse) -> eyre::Result { - let code = Self::generate_from_schema( - schema - .as_schema() - .schema - .as_ref() - .ok_or(eyre::anyhow!("could not get schema to generate code from"))?, - )?; - Ok(code) - } - - fn generate_from_schema(schema: &Schema) -> eyre::Result { - let mut output = String::new(); - output.push_str("# code generated by dagger. DO NOT EDIT."); - - let types = get_types(schema)?; - //let remaining: Vec> = types.into_iter().map(type_name).collect(); - - todo!() - } -} - -fn get_types(schema: &Schema) -> eyre::Result> { - let types = schema - .types - .as_ref() - .ok_or(eyre::anyhow!("types not found on schema"))?; - - // 1. Get a list of all types and map it to handlers - let types: Vec<&FullType> = types - .iter() - .map(|t| t.as_ref().map(|t| &t.full_type)) - .flatten() - .collect(); - - Ok(types) -} - -fn type_name(t: &FullType) -> Option { - let name = t.name.as_ref(); - if let Some(name) = name { - if name.starts_with("_") || !is_custom_scalar_type(t) { - return None; - } - - return Some(name.replace("Query", "Client")); - } - - None -} - -fn is_scalar_type(t: &FullType) -> bool { - if let Some(introspection_response::__TypeKind::SCALAR) = t.kind { - return true; - } - false -} - -enum Scalars { - ID(String), - Int(usize), - String(String), - Float(f64), - Boolean(bool), - Date(String), - DateTime(String), - Time(String), - Decimal(f64), -} - -fn is_custom_scalar_type(t: &FullType) -> bool { - if is_scalar_type(t) { - let _ = match t.name.as_ref().map(|s| s.as_str()) { - Some("ID") => Scalars::ID("ID".into()), - Some("Int") => Scalars::Int(0), - Some("String") => Scalars::String("ID".into()), - Some("Float") => Scalars::Float(0.0), - Some("Boolean") => Scalars::Boolean(false), - Some("Date") => Scalars::Date("ID".into()), - Some("DateTime") => Scalars::DateTime("ID".into()), - Some("Time") => Scalars::Time("ID".into()), - Some("Decimal") => Scalars::Decimal(0.0), - Some(_) => return true, - None => return false, - }; - } - false -} +mod codegen; +mod handlers; +mod models; +mod predicates; #[cfg(test)] mod tests { use graphql_introspection_query::introspection_response::IntrospectionResponse; - use super::CodeGeneration; + use crate::codegen::CodeGeneration; #[test] fn can_generate_from_schema() { let schema: IntrospectionResponse = serde_json::from_str(INTROSPECTION_QUERY).unwrap(); - let code = CodeGeneration::generate(&schema).unwrap(); + let code = CodeGeneration::new().generate(&schema).unwrap(); assert_eq!("some-code", code); } diff --git a/crates/dagger-codegen/src/models.rs b/crates/dagger-codegen/src/models.rs new file mode 100644 index 0000000..7ed5a54 --- /dev/null +++ b/crates/dagger-codegen/src/models.rs @@ -0,0 +1,11 @@ +pub enum Scalars { + ID(String), + Int(usize), + String(String), + Float(f64), + Boolean(bool), + Date(String), + DateTime(String), + Time(String), + Decimal(f64), +} diff --git a/crates/dagger-codegen/src/predicates.rs b/crates/dagger-codegen/src/predicates.rs new file mode 100644 index 0000000..c7887c4 --- /dev/null +++ b/crates/dagger-codegen/src/predicates.rs @@ -0,0 +1,30 @@ +use graphql_introspection_query::introspection_response::{self, FullType}; + +use crate::models::Scalars; + +pub fn is_scalar_type(t: &FullType) -> bool { + if let Some(introspection_response::__TypeKind::SCALAR) = t.kind { + return true; + } + false +} + +pub fn is_custom_scalar_type(t: &FullType) -> bool { + if is_scalar_type(t) { + // TODO: Insert scalar + let _ = match t.name.as_ref().map(|s| s.as_str()) { + Some("ID") => Scalars::ID("ID".into()), + Some("Int") => Scalars::Int(0), + Some("String") => Scalars::String("ID".into()), + Some("Float") => Scalars::Float(0.0), + Some("Boolean") => Scalars::Boolean(false), + Some("Date") => Scalars::Date("ID".into()), + Some("DateTime") => Scalars::DateTime("ID".into()), + Some("Time") => Scalars::Time("ID".into()), + Some("Decimal") => Scalars::Decimal(0.0), + Some(_) => return true, + None => return false, + }; + } + false +} diff --git a/crates/dagger-sdk/Cargo.toml b/crates/dagger-sdk/Cargo.toml index 4c7f897..93a7bd4 100644 --- a/crates/dagger-sdk/Cargo.toml +++ b/crates/dagger-sdk/Cargo.toml @@ -9,3 +9,4 @@ description = "A dagger sdk for rust, written in rust" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +genco = "0.17.3" diff --git a/src/cli_generate.rs b/src/cli_generate.rs index 8df6e0d..8780fe4 100644 --- a/src/cli_generate.rs +++ b/src/cli_generate.rs @@ -1,6 +1,6 @@ use clap::{Arg, ArgMatches}; -use crate::{code_generation::CodeGeneration, config::Config, engine::Engine, session::Session}; +use crate::{config::Config, engine::Engine, session::Session}; #[allow(dead_code)] pub struct GenerateCommand; @@ -17,12 +17,12 @@ impl GenerateCommand { let session = Session::new(); let req = session.start(&cfg, &conn)?; let schema = session.schema(req)?; - let code = CodeGeneration::generate(&schema)?; + //let code = CodeGeneration::generate(&schema)?; if let Some(output) = arg_matches.get_one::("output") { // TODO: Write to file } else { - println!("{}", code); + //println!("{}", code); } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index f4aeb48..376eedd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ pub mod cli; mod cli_generate; mod cli_session; -mod code_generation; mod config; mod connect_params; pub mod dagger;