Skip to content

Commit

Permalink
Release: remove most unwraps in favour of clearer 'expect' usage.
Browse files Browse the repository at this point in the history
  • Loading branch information
finnhodgkin committed Oct 2, 2024
1 parent a840b9c commit 3ba361b
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 51 deletions.
8 changes: 5 additions & 3 deletions src/build_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ pub async fn build_schema(
.header("x-hasura-role", &role)
.run_graphql(IntrospectionQuery::build(()))
.await
.unwrap()
.expect("Failed to fetch GraphQL introspection schema.")
.data
.unwrap();
.expect("Failed to parse GraphQL introspection schema.");

let schema = introspection_data.into_schema().unwrap();
let schema = introspection_data
.into_schema()
.expect("Failed to convert introspection data.");

// Create the purescript types;
let mut records: Vec<PurescriptRecord> = vec![];
Expand Down
37 changes: 26 additions & 11 deletions src/config/parse_outside_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,22 @@ pub fn fetch_all_outside_types(workspace_config: &WorkspaceConfig) -> OutsideTyp
}

pub fn fetch_outside_types(location: &str, workspace_config: &WorkspaceConfig) -> OutsideTypes {
let mut f = File::open(location).unwrap();
let mut f =
File::open(location).expect(&format!("Outside types yaml file not found at {location}"));
let mut s = String::new();
f.read_to_string(&mut s).unwrap();
f.read_to_string(&mut s)
.expect("Failed to read outside types file to string.");

let docs = yaml::YamlLoader::load_from_str(&s).unwrap();
let docs =
yaml::YamlLoader::load_from_str(&s).expect("Failed to parse outside types file as yaml.");
if let Yaml::Hash(hash) = &docs[0] {
let types = to_types(hash.get(&Yaml::String("types".to_string())));
let templates: HashMap<String, Object> =
to_templates(hash.get(&Yaml::String("templates".to_string())), &types);

let outside_types = to_outside_types(
hash.get(&Yaml::String("outside_types".to_string()))
.unwrap(),
.expect("Your outside types yaml should have a top level key 'outside_types'"),
&types,
&templates,
);
Expand Down Expand Up @@ -80,14 +83,14 @@ fn to_types(yaml: Option<&Yaml>) -> impl Fn(&str, &str) -> Option<Mod> {
.split(", ")
.collect::<Vec<&str>>()
.get(1)
.unwrap()
.expect(&format!("No import found for type {name}"))
.replace("$", type_name),
name: type_name.to_string(),
package: import
.split(", ")
.collect::<Vec<&str>>()
.get(2)
.unwrap()
.expect(&format!("No package found for type {name}"))
.to_string(),
}),
None => None,
Expand Down Expand Up @@ -167,15 +170,27 @@ fn to_templates(
fn to_type_value(type_value: &String, types_fn: &impl Fn(&str, &str) -> Option<Mod>) -> Mod {
if type_value.contains('=') {
types_fn(
type_value.split('=').next().unwrap(),
type_value.split('=').last().unwrap(),
type_value
.split('=')
.next()
.expect(&format!("No type name found before '=' for: {type_value}.")),
type_value
.split('=')
.last()
.expect(&format!("No type value found after '=' for: {type_value}.")),
)
.unwrap_or_else(|| panic!("Type not found: {}", type_value))
} else if type_value.contains(", ") {
let mut values = type_value.split(", ");
let name = values.next().unwrap();
let import = values.next().unwrap();
let package: &str = values.next().unwrap();
let name = values
.next()
.expect(&format!("No type name found for inline type {type_value}."));
let import = values.next().expect(&format!(
"No import found (second comma separated value) for inline type {type_value}."
));
let package: &str = values.next().expect(&format!(
"No package found (third comma separated value) for inline type {type_value}."
));
Mod {
import: import.to_string(),
name: name.to_string(),
Expand Down
7 changes: 4 additions & 3 deletions src/config/parse_roles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ use yaml_rust2::{yaml, Yaml};

pub fn parse_roles() -> Vec<String> {
let file_path: String = std::env::var("ROLES_YAML").expect("ROLES_YAML must be set");
let mut f = File::open(file_path).unwrap();
let mut f = File::open(file_path).expect("Failed to locate or open roles yaml file.");
let mut s = String::new();
f.read_to_string(&mut s).unwrap();
f.read_to_string(&mut s)
.expect("Failed to read roles yaml file to string.");

let docs = yaml::YamlLoader::load_from_str(&s).unwrap();
let docs = yaml::YamlLoader::load_from_str(&s).expect("Failed to parse roles YAML as YAML.");
if let Yaml::Array(docs) = &docs[0] {
let mut roles: Vec<String> = Vec::new();
for docs in docs {
Expand Down
41 changes: 32 additions & 9 deletions src/config/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ use yaml_rust2::{yaml, Yaml};
pub async fn parse_workspace() -> Result<WorkspaceConfig> {
let file_path: String = std::env::var("SPAGO_WORKSPACE_CONFIG_YAML")
.expect("SPAGO_WORKSPACE_CONFIG_YAML must be set");
let mut f = File::open(file_path).await.unwrap();
let mut f = File::open(file_path)
.await
.expect("Failed to locate or open spago workspace config yaml.");
let mut s = String::new();

f.read_to_string(&mut s).await.unwrap();
f.read_to_string(&mut s)
.await
.expect("Failed to read spago workspace config yaml file to string.");

let docs = yaml::YamlLoader::load_from_str(&s).unwrap();
let docs =
yaml::YamlLoader::load_from_str(&s).expect("Failed to parse workspace YAML as YAML.");

if let Yaml::Hash(hash) = &docs[0] {
match WorkspaceConfig::new(hash) {
Expand Down Expand Up @@ -47,12 +52,30 @@ impl WorkspaceConfig {
let schema_libs_dir = yaml_hash.get(&Yaml::String("schema_libs_dir".to_string()))?;

Some(Self {
postgres_enums_lib: postgres_enums_lib.as_str().unwrap().to_string(),
postgres_enums_dir: postgres_enums_dir.as_str().unwrap().to_string(),
shared_graphql_enums_lib: shared_graphql_enums_lib.as_str().unwrap().to_string(),
shared_graphql_enums_dir: shared_graphql_enums_dir.as_str().unwrap().to_string(),
schema_libs_prefix: schema_libs_prefix.as_str().unwrap().to_string(),
schema_libs_dir: schema_libs_dir.as_str().unwrap().to_string(),
postgres_enums_lib: postgres_enums_lib
.as_str()
.expect("Workspace yaml should contain postgres_enums_lib key.")
.to_string(),
postgres_enums_dir: postgres_enums_dir
.as_str()
.expect("Workspace yaml should contain postgres_enums_dir key.")
.to_string(),
shared_graphql_enums_lib: shared_graphql_enums_lib
.as_str()
.expect("Workspace yaml should contain shared_graphql_enums_lib key.")
.to_string(),
shared_graphql_enums_dir: shared_graphql_enums_dir
.as_str()
.expect("Workspace yaml should contain shared_graphql_enums_dir key.")
.to_string(),
schema_libs_prefix: schema_libs_prefix
.as_str()
.expect("Workspace yaml should contain schema_libs_prefix key.")
.to_string(),
schema_libs_dir: schema_libs_dir
.as_str()
.expect("Workspace yaml should contain schema_libs_dir key.")
.to_string(),
})
}
}
17 changes: 14 additions & 3 deletions src/enums/generate_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ pub async fn generate_enum(

// Empty enums in Hasura are represented as a single value with the name "_PLACEHOLDER"
// purescript enums cannot start with an underscore, so we need to replace it with a different placeholder
let values = if en.values.iter().next().unwrap().name == "_PLACEHOLDER" {
let values = if en
.values
.iter()
.next()
.expect("Enums should have at least one value.")
.name
== "_PLACEHOLDER"
{
vec!["ENUM_PLACEHOLDER".to_string()]
} else {
en.values.iter().map(|v| first_upper(&v.name)).collect()
Expand Down Expand Up @@ -150,8 +157,12 @@ fn enum_instances(name: &str, values: &Vec<String>, original_values: &Vec<String

instances.push_str(&format!(
"\n\ninstance Bounded {name} where\n top = {}\n bottom = {}",
values.last().unwrap(),
values.first().unwrap()
values
.last()
.expect("Enums should have at least one value in order to get last."),
values
.first()
.expect("Enums should have at least one value in order to get first.")
));

instances.push_str(&format!(
Expand Down
15 changes: 11 additions & 4 deletions src/enums/postgres_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ pub async fn fetch_types(
if db_env.is_err() {
return Ok(HashMap::new());
}
let database_url = db_env.unwrap();
let database_url =
db_env.expect("DATABASE_URL should not be required but for some reason is...");
let pool = PgPoolOptions::new()
.max_connections(1)
.connect(&database_url)
Expand Down Expand Up @@ -162,8 +163,12 @@ all{name} =

instances.push_str(&format!(
"\n\ninstance Bounded {name} where\n top = {}\n bottom = {}",
values.last().unwrap(),
values.first().unwrap()
values
.last()
.expect("Postgres enum should have at least one value to get last."),
values
.first()
.expect("Postgres enum should have at least one value to get first.")
));

instances.push_str(&format!(
Expand Down Expand Up @@ -227,7 +232,9 @@ all{name} =
instances.push_str(&format!(
"\n\ninstance MakeFixture {} where\n mkFixture = {}",
name,
values.first().unwrap()
values
.first()
.expect("Postgres enum should have at least one value to get first.")
));

instances
Expand Down
8 changes: 6 additions & 2 deletions src/hasura_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,11 @@ fn outside_type(
}
}
(Some((package, import)), type_)
} else if let Some((package, import, type_)) = purs_types.lock().unwrap().get(name) {
} else if let Some((package, import, type_)) = purs_types
.lock()
.expect("Failed to lock purs type to thread.")
.get(name)
{
(Some((package.clone(), import.clone())), type_.clone())
} else {
(None, base_types(name).to_string())
Expand All @@ -105,7 +109,7 @@ fn get_outside_type(
) -> Option<(String, String, String)> {
outside_types
.lock()
.unwrap()
.expect("Failed to lock outside types to thread.")
.get(object)
.map(|table| table.get(field))
.flatten()
Expand Down
10 changes: 8 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ async fn main() -> Result<()> {
let workspace_config = parse_workspace().await?;

// Generate postgres enum types
let postgres_types = fetch_types(&workspace_config).await.unwrap();
let postgres_types = fetch_types(&workspace_config)
.await
.expect("Failed to generate postgres enum types.");
let num_types = postgres_types.len();

println!(
Expand Down Expand Up @@ -66,7 +68,11 @@ async fn main() -> Result<()> {
// Join the results
let mut outputs = Vec::with_capacity(tasks.len());
for task in tasks {
outputs.push(task.await.unwrap().unwrap());
outputs.push(
task.await
.expect("Failed to build schema gen task output")
.expect("Failed to join schema gen task output"),
);
}

println!(
Expand Down
39 changes: 28 additions & 11 deletions src/main_check_needs_migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use sqlx::{postgres::PgPoolOptions, Result};
#[tokio::main]
async fn main() -> Result<()> {
dotenv().ok();
let db_env = std::env::var("DATABASE_URL").unwrap();
let db_env = std::env::var("DATABASE_URL").expect("DATABASE_URL var must be set.");
let pool = PgPoolOptions::new()
.max_connections(1)
.connect(&db_env)
Expand All @@ -20,8 +20,10 @@ async fn main() -> Result<()> {
.fetch_one(&pool)
.await?;

let test_db = std::env::var("TEST_DATABASE_URL").unwrap();
let hasura_migrations_dir = std::env::var("HASURA_MIGRATIONS_DIR").unwrap();
let test_db = std::env::var("TEST_DATABASE_URL")
.expect("TEST_DATABASE_URL must be set so we can use it as a codegen base.");
let hasura_migrations_dir =
std::env::var("HASURA_MIGRATIONS_DIR").expect("HASURA_MIGRATIONS_DIR must be set.");
let test_pool = PgPoolOptions::new()
.max_connections(1)
.connect(&test_db)
Expand All @@ -34,7 +36,9 @@ async fn main() -> Result<()> {
.fetch_one(&test_pool)
.await?;

let migrations: Value = serde_json::from_str(&standard_result.migrations).unwrap();
let migrations: Value = serde_json::from_str(&standard_result.migrations).expect(
"Failed to parse hasura migrations json. Perhaps your Hasura version is mismatched.",
);
let test_migrations: Value = serde_json::from_str(&test_result.migrations).unwrap();

let migrations_obj = migrations.as_object().unwrap();
Expand All @@ -53,21 +57,34 @@ async fn main() -> Result<()> {
}
}

let last_test = test_migrations_obj.iter().last().unwrap().0.clone();
let last = migrations_obj.iter().last().unwrap().0.clone();
let last_test = test_migrations_obj
.iter()
.last()
.expect("Must have at least one migration in test database.") // TODO make this optional?
.0
.clone();
let last = migrations_obj
.iter()
.last()
.expect("Must have at least one migration in your database.") // TODO again, make this optional?
.0
.clone();

let mut time_stamps = vec![];
let files = fs::read_dir(hasura_migrations_dir).unwrap();
let files =
fs::read_dir(hasura_migrations_dir).expect("The chosen Hasura directory must exist.");
for entry in files {
let path = entry.unwrap().path();
let path = entry
.expect("Failed to parse path in Hasura directory.")
.path();
let timestamp = path
.file_name()
.unwrap()
.expect("Failed to parse file name in Hasura dir.")
.to_str()
.unwrap()
.expect("Failed to convert file name to string in Hasura dir.")
.split("_")
.next()
.unwrap();
.expect("Failed to split timestamp out of file name in Hasura migrations dir.");
time_stamps.push(timestamp.to_string());
}
time_stamps.sort();
Expand Down
8 changes: 7 additions & 1 deletion src/purescript_gen/purescript_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ impl Field {
}
pub fn show_field(&self) -> String {
// if first character is uppercase, wrap in quotes
if self.name.chars().next().unwrap().is_uppercase() {
if self
.name
.chars()
.next()
.expect("Field should not be an empty string.")
.is_uppercase()
{
format!("\"{}\"", self.name)
} else {
self.name.clone()
Expand Down
4 changes: 2 additions & 2 deletions src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{fs, path::Path};
pub fn write(path: &str, contents: &str) -> () {
let file_name = Path::new(path);
if let Some(p) = file_name.parent() {
fs::create_dir_all(p).unwrap();
fs::create_dir_all(p).expect("Failed to create directory for new file.");
};
fs::write(file_name, contents).unwrap();
fs::write(file_name, contents).expect(&format!("Failed to write file."));
}

0 comments on commit 3ba361b

Please sign in to comment.