Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion purs/app/spago.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ package:
- variant
- oa-gql-schema-all-users
- oa-enums
- oa-gql-enums
- gql-enums
test:
main: Test.Main
dependencies:
Expand Down
116 changes: 73 additions & 43 deletions src/build_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ use cynic_introspection::{
Directive, DirectiveLocation, FieldWrapping, InputValue, InterfaceType, IntrospectionQuery,
Type, UnionType, WrappingType,
};
use stringcase::{kebab_case, pascal_case};
use stringcase::kebab_case;
use tokio::task::spawn_blocking;

use crate::{
config::{
parse_outside_types::{Mod, OutsideTypes}, parse_scalar_types::ScalarTypes,
parse_outside_types::{Mod, OutsideTypes},
parse_scalar_types::ScalarTypes,
workspace::WorkspaceConfig,
},
enums::generate_enum::generate_enum,
Expand All @@ -28,6 +29,7 @@ use crate::{
purescript_record::{show_field_name, Field, PurescriptRecord},
purescript_type::PurescriptType,
purescript_variant::Variant,
upper_first::upper_first,
},
write::write,
};
Expand Down Expand Up @@ -97,41 +99,57 @@ pub async fn build_schema(
// Adds the root schema record
let mut schema_record = PurescriptRecord::new("Schema");

// The schema must always at least have a query type, add it now.
let query_type = PurescriptType::new(
"Query",
vec![],
Argument::new_type(&pascal_case(schema.query_type.as_str())),
);
schema_record.add_field(Field::new("query").with_type(&query_type.name));
types.push(query_type);

// Add the directives field (imported above)
schema_record.add_field(Field::new("directives").with_type_arg(
Argument::new_type("Proxy").with_argument(Argument::new_type("Directives")),
));

// Optionally add mutation
if let Some(mut_type) = &schema.mutation_type {
let mutation_type = PurescriptType::new(
"Mutation",
vec![],
Argument::new_type(&pascal_case(&mut_type)),
);
schema_record.add_field(Field::new("mutation").with_type(&mutation_type.name));
types.push(mutation_type);
};

// and subscription types
if let Some(mut_type) = &schema.subscription_type {
let mutation_type = PurescriptType::new(
"Subscription",
if workspace_config.create_root_aliases {
let query_type = PurescriptType::new(
"Query",
vec![],
Argument::new_type(&pascal_case(&mut_type)),
Argument::new_type(&upper_first(schema.query_type.as_str())),
);
schema_record.add_field(Field::new("subscription").with_type(&mutation_type.name));
types.push(mutation_type);
};

schema_record.add_field(Field::new("query").with_type(&query_type.name));
types.push(query_type);

// Optionally add mutation
if let Some(mut_type) = &schema.mutation_type {
let mutation_type = PurescriptType::new(
"Mutation",
vec![],
Argument::new_type(&upper_first(&mut_type)),
);
schema_record.add_field(Field::new("mutation").with_type(&mutation_type.name));
types.push(mutation_type);
};

// and subscription types
if let Some(sub_type) = &schema.subscription_type {
let sub_type = PurescriptType::new(
"Subscription",
vec![],
Argument::new_type(&upper_first(&sub_type)),
);
schema_record.add_field(Field::new("subscription").with_type(&sub_type.name));
types.push(sub_type);
};
} else {
schema_record.add_field(Field::new("query").with_type(&schema.query_type));

// Optionally add mutation
if let Some(mut_type) = &schema.mutation_type {
schema_record.add_field(Field::new("mutation").with_type(&mut_type));
};

// and subscription types
if let Some(sub_type) = &schema.subscription_type {
schema_record.add_field(Field::new("subscription").with_type(&sub_type));
};
}

// The schema must always at least have a query type, add it now.

// Process the schema types
for type_ in schema.types.iter() {
Expand All @@ -142,7 +160,7 @@ pub async fn build_schema(
}

// Convert the gql_type_name to a PurescriptTypeName
let name = pascal_case(&obj.name);
let name = upper_first(&obj.name);

// Creates a new record for the object
let mut record = PurescriptRecord::new("Ignored");
Expand All @@ -163,6 +181,7 @@ pub async fn build_schema(
&mut imports,
&postgres_types,
&outside_types,
&scalar_types,
),
&arg.ty.wrapping,
&mut imports,
Expand All @@ -183,6 +202,7 @@ pub async fn build_schema(
&mut imports,
&postgres_types,
&outside_types,
&scalar_types,
),
&field.ty.wrapping,
&mut imports,
Expand Down Expand Up @@ -218,19 +238,28 @@ pub async fn build_schema(
add_import("argonaut-core", "Data.Argonaut.Core", "Json", &mut imports)
}
"time" => add_import("datetime", "Data.Time", "Time", &mut imports),
scalar_name => {
match scalar_types.lock().unwrap().get(scalar_name) {
Some(Mod { package, import, name }) => {
add_import(package, import, name, &mut imports);
types.push(PurescriptType::new(scalar_name, vec![], Argument::new_type(name)));
scalar_name => match scalar_types.lock().unwrap().get(scalar_name) {
Some(Mod {
package,
import,
name,
}) => {
add_import(package, import, name, &mut imports);
types.push(PurescriptType::new(
&&upper_first(scalar_name),
vec![],
Argument::new_type(name),
));
}
None => {
add_import("argonaut-core", "Data.Argonaut.Core", "Json", &mut imports);
types.push(PurescriptType::new(scalar_name, vec![], Argument::new_type("Json")));

add_import("argonaut-core", "Data.Argonaut.Core", "Json", &mut imports);
types.push(PurescriptType::new(
&upper_first(scalar_name),
vec![],
Argument::new_type("Json"),
));
}
}
}
},
}
}
Type::Enum(en) => {
Expand All @@ -255,7 +284,7 @@ pub async fn build_schema(
}

// Convert the gql_type_name to a PurescriptTypeName
let name = pascal_case(&obj.name);
let name: String = upper_first(&obj.name);

// Build a purescript record with all fields
let mut record = PurescriptRecord::new("Query");
Expand All @@ -270,6 +299,7 @@ pub async fn build_schema(
&mut imports,
&postgres_types,
&outside_types,
&scalar_types,
),
&field.ty.wrapping,
&mut imports,
Expand Down Expand Up @@ -318,7 +348,7 @@ pub async fn build_schema(
union.with_values(
&possible_types
.iter()
.map(|t| (t.clone(), pascal_case(&t)))
.map(|t| (t.clone(), upper_first(&t)))
.collect(),
);

Expand Down
7 changes: 7 additions & 0 deletions src/config/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,11 @@ pub struct WorkspaceConfig {
pub schema_libs_dir: String,
#[serde(default = "Vec::new")]
pub variant_enums: Vec<String>,
#[serde(default = "mk_false")]
pub create_root_aliases: bool,
pub enums_package_name: String,
}

fn mk_false () -> bool {
false
}
30 changes: 17 additions & 13 deletions src/enums/generate_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub async fn generate_enum(
en.values.iter().map(|v| upper_first(&v.name)).collect()
};
let original_values: Vec<String> = en.values.iter().map(|v| v.name.clone()).collect();
let name: String = pascal_case(&en.name);
let name: String = upper_first(&en.name);

// Some enums are shared between all schemas
// Hasura suffixes 'Enum' to the end of custom enums created
Expand All @@ -51,7 +51,8 @@ pub async fn generate_enum(
&workspace_config.shared_graphql_enums_lib
);
let package_name = pascal_case(&workspace_config.shared_graphql_enums_lib);
let module_name = format!("{package_name}.{name}");
let name_pascal = pascal_case(&name);
let module_name = format!("{package_name}.{name_pascal}");
let helper_module = format!("{package_name}.Utils.VariantHelpers");
if let Some(variant) = variant_mod(
&name,
Expand All @@ -60,17 +61,17 @@ pub async fn generate_enum(
&format!("\nimport {helper_module} (var, match)"),
) {
imports
.push(PurescriptImport::new(&module_name, "oa-gql-enums").add_specified(&name));
.push(PurescriptImport::new(&module_name, &workspace_config.enums_package_name).add_specified(&name));

write(
&format!("{lib_path}/src/{package_name}/{name}.purs"),
&format!("{lib_path}/src/{package_name}/{module_name}.purs"),
&variant,
);
write(
&format!("{lib_path}/src/{package_name}/Utils/VariantHelpers.purs"),
&format!("module {helper_module} where \n{VARIANT_HELPERS_MOD}"),
);
write(&format!("{lib_path}/spago.yaml"), &enums_spago_yaml());
write(&format!("{lib_path}/spago.yaml"), &enums_spago_yaml(&workspace_config.enums_package_name));
}

None
Expand All @@ -79,21 +80,22 @@ pub async fn generate_enum(

let instances = enum_instances(&name, &values, &original_values);
let package_name = pascal_case(&workspace_config.shared_graphql_enums_lib);
let module_name = format!("{package_name}.{name}");
imports.push(PurescriptImport::new(&module_name, "oa-gql-enums").add_specified(&name));
let name_pascal = pascal_case(&name);
let module_name = format!("{package_name}.{name_pascal}");
imports.push(PurescriptImport::new(&module_name, &workspace_config.enums_package_name).add_specified(&name));

let lib_path = format!(
"{}{}",
&workspace_config.shared_graphql_enums_dir,
&workspace_config.shared_graphql_enums_lib
);
write(
&format!("{lib_path}/src/{package_name}/{name}.purs"),
&format!("{lib_path}/src/{package_name}/{name_pascal}.purs"),
&format!(
"module {module_name} ({name}(..)) where\n\n{MODULE_IMPORTS}\n\n{e}{instances}"
),
);
write(&format!("{lib_path}/spago.yaml"), &enums_spago_yaml());
write(&format!("{lib_path}/spago.yaml"), &enums_spago_yaml(&workspace_config.enums_package_name));
None
}
// Otherwise write schema-specific variant enums
Expand Down Expand Up @@ -397,9 +399,11 @@ fn to_variant(type_name: &str, name: &str) -> String {
)
}

fn enums_spago_yaml() -> String {
fn enums_spago_yaml(package_name: &str) -> String {

format!(
r#"package:
name: oa-gql-enums
name: {package_name}
dependencies:
- argonaut
- argonaut-codecs
Expand All @@ -416,8 +420,8 @@ fn enums_spago_yaml() -> String {
- variant
- oa-make-fixture
- oa-encode-decode
"#
.to_string()
"#)

}

const MODULE_IMPORTS: &str = r#"import Prelude
Expand Down
Loading
Loading