Skip to content

Commit c6e5ae4

Browse files
committed
adds support for custom scalars
1 parent 0e6131d commit c6e5ae4

File tree

7 files changed

+72
-34
lines changed

7 files changed

+72
-34
lines changed

Cargo.lock

Lines changed: 23 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ stringcase = "0.3.0"
1818
tokio = { version = "1.40.0", features = ["full"] }
1919
yaml-rust2 = "0.8.1"
2020
serde_json = "1.0"
21+
serde = "1.0"
22+
serde_derive = "1.0"
23+
serde_yaml = "0.9.34"
2124

2225
[[bin]]
2326
edition = "2021"

src/build_schema.rs

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::{
22
collections::HashMap,
3-
fmt::format,
43
sync::{Arc, Mutex},
54
thread::Result,
65
};
@@ -10,11 +9,14 @@ use cynic_introspection::{
109
Directive, DirectiveLocation, FieldWrapping, InputValue, InterfaceType, IntrospectionQuery,
1110
Type, UnionType, WrappingType,
1211
};
13-
use stringcase::{kebab_case};
12+
use stringcase::{kebab_case, pascal_case};
1413
use tokio::task::spawn_blocking;
1514

1615
use crate::{
17-
config::{parse_outside_types::OutsideTypes, workspace::WorkspaceConfig},
16+
config::{
17+
parse_outside_types::{Mod, OutsideTypes}, parse_scalar_types::ScalarTypes,
18+
workspace::WorkspaceConfig,
19+
},
1820
enums::generate_enum::generate_enum,
1921
hasura_types::as_gql_field,
2022
purescript_gen::{
@@ -26,7 +28,6 @@ use crate::{
2628
purescript_record::{show_field_name, Field, PurescriptRecord},
2729
purescript_type::PurescriptType,
2830
purescript_variant::Variant,
29-
upper_first::*,
3031
},
3132
write::write,
3233
};
@@ -35,6 +36,7 @@ pub async fn build_schema(
3536
role: String,
3637
postgres_types: Arc<Mutex<HashMap<String, (String, String, String)>>>,
3738
outside_types: Arc<Mutex<OutsideTypes>>,
39+
scalar_types: Arc<Mutex<ScalarTypes>>,
3840
workspace_config: WorkspaceConfig,
3941
) -> Result<()> {
4042
// Fetch the introspection schema
@@ -99,7 +101,7 @@ pub async fn build_schema(
99101
let query_type = PurescriptType::new(
100102
"Query",
101103
vec![],
102-
Argument::new_type(&upper_first(schema.query_type.as_str())),
104+
Argument::new_type(&pascal_case(schema.query_type.as_str())),
103105
);
104106
schema_record.add_field(Field::new("query").with_type(&query_type.name));
105107
types.push(query_type);
@@ -114,7 +116,7 @@ pub async fn build_schema(
114116
let mutation_type = PurescriptType::new(
115117
"Mutation",
116118
vec![],
117-
Argument::new_type(&upper_first(&mut_type)),
119+
Argument::new_type(&pascal_case(&mut_type)),
118120
);
119121
schema_record.add_field(Field::new("mutation").with_type(&mutation_type.name));
120122
types.push(mutation_type);
@@ -125,7 +127,7 @@ pub async fn build_schema(
125127
let mutation_type = PurescriptType::new(
126128
"Subscription",
127129
vec![],
128-
Argument::new_type(&upper_first(&mut_type)),
130+
Argument::new_type(&pascal_case(&mut_type)),
129131
);
130132
schema_record.add_field(Field::new("subscription").with_type(&mutation_type.name));
131133
types.push(mutation_type);
@@ -140,7 +142,7 @@ pub async fn build_schema(
140142
}
141143

142144
// Convert the gql_type_name to a PurescriptTypeName
143-
let name = upper_first(&obj.name);
145+
let name = pascal_case(&obj.name);
144146

145147
// Creates a new record for the object
146148
let mut record = PurescriptRecord::new("Ignored");
@@ -201,11 +203,12 @@ pub async fn build_schema(
201203
types.push(query_type);
202204
};
203205
match type_ {
204-
Type::Object(obj) => handle_obj(obj),
206+
Type::Object(obj) => handle_obj(&obj),
205207
Type::Scalar(scalar) => {
206208
// Add imports for common scalar types if they are used.
207209
// TODO maybe move these to config so they can be updated outside of rust
208210
match scalar.name.as_str() {
211+
"ID" => add_import("graphql-client", "GraphQL.Client.ID", "ID", &mut imports),
209212
_ if scalar.is_builtin() => {} // ignore built in types like String, Int, etc.
210213
"date" => add_import("datetime", "Data.Date", "Date", &mut imports),
211214
"timestamp" | "timestamptz" => {
@@ -215,8 +218,19 @@ pub async fn build_schema(
215218
add_import("argonaut-core", "Data.Argonaut.Core", "Json", &mut imports)
216219
}
217220
"time" => add_import("datetime", "Data.Time", "Time", &mut imports),
218-
"ID" => add_import("graphql-client", "GraphQL.Client.ID", "ID", &mut imports),
219-
_ => {}
221+
scalar_name => {
222+
match scalar_types.lock().unwrap().get(scalar_name) {
223+
Some(Mod { package, import, name }) => {
224+
add_import(package, import, name, &mut imports);
225+
types.push(PurescriptType::new(scalar_name, vec![], Argument::new_type(name)));
226+
}
227+
None => {
228+
add_import("argonaut-core", "Data.Argonaut.Core", "Json", &mut imports);
229+
types.push(PurescriptType::new(scalar_name, vec![], Argument::new_type("Json")));
230+
231+
}
232+
}
233+
}
220234
}
221235
}
222236
Type::Enum(en) => {
@@ -241,7 +255,7 @@ pub async fn build_schema(
241255
}
242256

243257
// Convert the gql_type_name to a PurescriptTypeName
244-
let name = upper_first(&obj.name);
258+
let name = pascal_case(&obj.name);
245259

246260
// Build a purescript record with all fields
247261
let mut record = PurescriptRecord::new("Query");
@@ -304,7 +318,7 @@ pub async fn build_schema(
304318
union.with_values(
305319
&possible_types
306320
.iter()
307-
.map(|t| (t.clone(), upper_first(&t)))
321+
.map(|t| (t.clone(), pascal_case(&t)))
308322
.collect(),
309323
);
310324

@@ -467,13 +481,7 @@ fn directive_type_str(directive: &Directive) -> Option<String> {
467481
.map(input_value_type_str)
468482
.collect::<Vec<String>>()
469483
.join("\n , ");
470-
let locations = directive_locations_str(&directive.locations);
471-
472-
if locations.is_none() {
473-
return None
474-
}
475-
476-
let locations = locations.unwrap();
484+
let locations = directive_locations_str(&directive.locations)?;
477485

478486
Some(format!("( Directive \"{name}\" \n \"{description}\" \n {{ {args} }} \n {locations} \n )"))
479487
}
@@ -542,7 +550,6 @@ fn build_directives(lib_path: String, role: String, directives: Vec<Directive>)
542550
"module {role}.Directives where \n{DIRECTIVE_IMPORTS}\ntype Directives :: List' Type\n{directive_str}\n\n{directive_fns}"
543551
));
544552

545-
546553
write(
547554
&format!("{lib_path}/src/{role}/Directives.purs"),
548555
&directive_mod,

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod parse_outside_types;
22
pub mod parse_roles;
33
pub mod workspace;
4+
pub mod parse_scalar_types;

src/config/parse_outside_types.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use std::{
44
io::Read,
55
};
66

7+
use serde::Deserialize;
8+
use stringcase::pascal_case;
79
use yaml_rust2::{yaml, Yaml};
810

9-
use crate::{purescript_gen::upper_first::upper_first, write::write};
11+
use crate::write::write;
1012

1113
use super::workspace::WorkspaceConfig;
1214

@@ -200,7 +202,7 @@ fn to_type_value(type_value: &String, types_fn: &impl Fn(&str, &str) -> Option<M
200202
}
201203
}
202204

203-
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
205+
#[derive(Debug, Clone, Eq, Hash, PartialEq, Deserialize)]
204206
pub struct Mod {
205207
pub import: String,
206208
pub name: String,
@@ -217,8 +219,8 @@ fn write_types(outside_types: &OutsideTypes, workspace_config: &WorkspaceConfig)
217219
let mock_outside_types = std::env::var("MOCK_OUTSIDE_TYPES");
218220
if mock_outside_types.is_ok() {
219221
let lib_path = workspace_config.shared_graphql_enums_dir.clone();
220-
let postgres_enums_lib = upper_first(&(&workspace_config.postgres_enums_lib).clone().unwrap());
221-
let gql_enums_lib = upper_first(&workspace_config.shared_graphql_enums_lib);
222+
let postgres_enums_lib = pascal_case(&(&workspace_config.postgres_enums_lib).clone().unwrap());
223+
let gql_enums_lib = pascal_case(&workspace_config.shared_graphql_enums_lib);
222224
for module in to_write.iter() {
223225
let is_enum_mod = module.import.contains(&postgres_enums_lib)
224226
|| module.import.contains(&gql_enums_lib);

src/hasura_types.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ use std::{
33
sync::{Arc, Mutex},
44
};
55

6+
use stringcase::pascal_case;
7+
68
use crate::{
79
config::parse_outside_types::{Mod, OutsideTypes},
8-
purescript_gen::{purescript_argument::Argument, purescript_import::PurescriptImport, upper_first::upper_first},
10+
purescript_gen::{purescript_argument::Argument, purescript_import::PurescriptImport},
911
};
1012

1113
pub fn as_gql_field(
@@ -25,7 +27,7 @@ pub fn as_gql_field(
2527
}
2628
Argument::new_type("AsGql")
2729
.with_argument(Argument::new_type(&format!("\"{}\"", name)))
28-
.with_argument(Argument::new_type(&upper_first(&type_)))
30+
.with_argument(Argument::new_type(&pascal_case(&type_)))
2931
}
3032

3133
fn outside_type(

src/main.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
use std::{
2-
fs::remove_dir_all,
3-
sync::{Arc, Mutex},
4-
thread::Result,
2+
collections::HashMap, fs::remove_dir_all, sync::{Arc, Mutex}, thread::Result
53
};
64

75
use build_schema::build_schema;
86
use config::{
9-
parse_outside_types::{fetch_all_outside_types, OutsideTypes},
10-
parse_roles::parse_roles,
11-
workspace::parse_workspace,
7+
parse_outside_types::{fetch_all_outside_types, OutsideTypes}, parse_roles::parse_roles, parse_scalar_types::{fetch_all_scalar_types, ScalarTypes}, workspace::parse_workspace
128
};
9+
use cynic_introspection::ScalarType;
1310
use dotenv::dotenv;
1411
use enums::postgres_types::fetch_types;
1512
use tokio::spawn;
@@ -63,13 +60,16 @@ async fn main() -> Result<()> {
6360
// Parse all outside type config
6461
let outside_types: OutsideTypes = fetch_all_outside_types(&workspace_config);
6562

63+
let scalar_types: ScalarTypes = fetch_all_scalar_types().unwrap_or(HashMap::new());
64+
6665
// Fetch role config
6766
let roles: Vec<String> = parse_roles();
6867
let num_roles = roles.len();
6968

7069
// Postgres types are shared between all roles
7170
let types_ = Arc::new(Mutex::new(postgres_types));
7271
let outside_types = Arc::new(Mutex::new(outside_types));
72+
let scalar_types = Arc::new(Mutex::new(scalar_types));
7373

7474
// Run schema gen for each role concurrently
7575
let mut tasks = Vec::with_capacity(num_roles);
@@ -79,6 +79,7 @@ async fn main() -> Result<()> {
7979
role.clone(),
8080
types_.clone(),
8181
outside_types.clone(),
82+
scalar_types.clone(),
8283
workspace_config.clone(),
8384
)));
8485
}

0 commit comments

Comments
 (0)