diff --git a/bin/sozo/src/commands/auth.rs b/bin/sozo/src/commands/auth.rs index 550ece1124..67ab7a5016 100644 --- a/bin/sozo/src/commands/auth.rs +++ b/bin/sozo/src/commands/auth.rs @@ -64,7 +64,7 @@ impl AuthArgs { trace!(metadata=?env_metadata, "Loaded environment."); let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws)?; match self.command { AuthCommand::Grant { kind, world, starknet, account, transaction } => { diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index da94807c98..8a21ef14dd 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -45,6 +45,23 @@ impl BuildArgs { pub fn run(self, config: &Config) -> Result<()> { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; + if let Ok(current_package) = ws.current_package() { + if current_package.target(&TargetKind::new("dojo")).is_none() { + return Err(anyhow::anyhow!( + "No Dojo target found in the {} package. Add [[target.dojo]] to the {} \ + manifest to enable Dojo features and compile with sozo.", + current_package.id.to_string(), + current_package.manifest_path() + )); + } + } + + // Namespaces are required to compute contracts/models data. Hence, we can't continue + // if no metadata are found. + // Once sozo will support package option, users will be able to do `-p` to select + // the package directly from the workspace instead of using `--manifest-path`. + let dojo_metadata = dojo_metadata_from_workspace(&ws)?; + let profile_name = ws.current_profile().expect("Scarb profile is expected at this point.").to_string(); @@ -126,13 +143,10 @@ impl BuildArgs { }; trace!(pluginManager=?bindgen, "Generating bindings."); - // Only generate bindgen if a current package is defined with dojo metadata. - if let Ok(dojo_metadata) = dojo_metadata_from_workspace(&ws) { - tokio::runtime::Runtime::new() - .unwrap() - .block_on(bindgen.generate(dojo_metadata.skip_migration)) - .expect("Error generating bindings"); - }; + tokio::runtime::Runtime::new() + .unwrap() + .block_on(bindgen.generate(dojo_metadata.skip_migration)) + .expect("Error generating bindings"); Ok(()) } diff --git a/bin/sozo/src/commands/call.rs b/bin/sozo/src/commands/call.rs index fcac0ac293..beb2497809 100644 --- a/bin/sozo/src/commands/call.rs +++ b/bin/sozo/src/commands/call.rs @@ -47,7 +47,7 @@ impl CallArgs { self.tag_or_address } else { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws)?; ensure_namespace(&self.tag_or_address, &default_namespace) }; diff --git a/bin/sozo/src/commands/execute.rs b/bin/sozo/src/commands/execute.rs index a100285df0..9d2dcf4faa 100644 --- a/bin/sozo/src/commands/execute.rs +++ b/bin/sozo/src/commands/execute.rs @@ -56,7 +56,7 @@ impl ExecuteArgs { self.tag_or_address } else { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws)?; ensure_namespace(&self.tag_or_address, &default_namespace) }; diff --git a/bin/sozo/src/commands/model.rs b/bin/sozo/src/commands/model.rs index c0e1997582..5ad4d5412e 100644 --- a/bin/sozo/src/commands/model.rs +++ b/bin/sozo/src/commands/model.rs @@ -113,7 +113,7 @@ impl ModelArgs { trace!(args = ?self); let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; let env_metadata = utils::load_metadata_from_config(config)?; - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws)?; config.tokio_handle().block_on(async { match self.command { diff --git a/bin/sozo/tests/register_test.rs b/bin/sozo/tests/register_test.rs index f9dd35f063..560ae8f103 100644 --- a/bin/sozo/tests/register_test.rs +++ b/bin/sozo/tests/register_test.rs @@ -28,7 +28,7 @@ async fn reregister_models() { let target_path = ws.target_dir().path_existent().unwrap().join(ws.config().profile().to_string()); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let migration = prepare_migration( source_project_dir.clone(), diff --git a/crates/dojo-lang/src/compiler.rs b/crates/dojo-lang/src/compiler.rs index 97eeff00b9..826d1dc4fc 100644 --- a/crates/dojo-lang/src/compiler.rs +++ b/crates/dojo-lang/src/compiler.rs @@ -87,7 +87,7 @@ impl Compiler for DojoCompiler { let props: Props = unit.main_component().target_props()?; let target_dir = unit.target_dir(ws); - let default_namespace = get_default_namespace_from_ws(ws); + let default_namespace = get_default_namespace_from_ws(ws)?; let compiler_config = build_compiler_config(&unit, ws); diff --git a/crates/dojo-world/src/metadata.rs b/crates/dojo-world/src/metadata.rs index 31774c5a3e..b796ae4636 100644 --- a/crates/dojo-world/src/metadata.rs +++ b/crates/dojo-world/src/metadata.rs @@ -53,10 +53,9 @@ fn build_artifact_from_filename( /// # Returns /// /// A [`String`] object containing the namespace. -pub fn get_default_namespace_from_ws(ws: &Workspace<'_>) -> String { - let metadata = dojo_metadata_from_workspace(ws) - .expect("Namespace key is already checked by the parsing of the Scarb.toml file."); - metadata.world.namespace +pub fn get_default_namespace_from_ws(ws: &Workspace<'_>) -> Result<String> { + let metadata = dojo_metadata_from_workspace(ws)?; + Ok(metadata.world.namespace) } /// Build world metadata with data read from the project configuration. @@ -99,13 +98,18 @@ pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> Result<DojoMetadata> let source_dir = source_dir.join(profile.as_str()); let project_metadata = if let Ok(current_package) = ws.current_package() { - current_package.manifest.metadata.dojo()? + current_package + .manifest + .metadata + .dojo() + .with_context(|| format!("Error parsing manifest file `{}`", ws.manifest_path()))? } else { // On workspaces, dojo metadata are not accessible because if no current package is defined // (being the only package or using --package). return Err(anyhow!( - "No current package with dojo metadata found, this subcommand is not yet support for \ - workspaces." + "No current package with dojo metadata found, virtual manifest in workspace are not \ + supported. Until package compilation is supported, you will have to provide the path \ + to the Scarb.toml file using the --manifest-path option." )); }; @@ -438,13 +442,14 @@ impl MetadataExt for ManifestMetadata { .tool_metadata .as_ref() .and_then(|e| e.get("dojo")) - // TODO: see if we can make error more descriptive - .ok_or_else(|| anyhow!("Some of the fields in [tool.dojo] are required."))? + .with_context(|| "No [tool.dojo] section found in the manifest.".to_string())? .clone(); + // The details of which field has failed to be loaded are logged inside the `try_into` + // error. let project_metadata: ProjectMetadata = metadata .try_into() - .with_context(|| "Project metadata (i.e. [tool.dojo]) is not properly configured.")?; + .with_context(|| "Project metadata [tool.dojo] is not properly configured.")?; Ok(project_metadata) } diff --git a/crates/sozo/ops/src/migration/mod.rs b/crates/sozo/ops/src/migration/mod.rs index 281bffc1f4..fda02e8325 100644 --- a/crates/sozo/ops/src/migration/mod.rs +++ b/crates/sozo/ops/src/migration/mod.rs @@ -78,7 +78,7 @@ where let target_dir = ws.target_dir().path_existent().unwrap(); let target_dir = target_dir.join(ws.config().profile().as_str()); - let default_namespace = get_default_namespace_from_ws(ws); + let default_namespace = get_default_namespace_from_ws(ws)?; // Load local and remote World manifests. let (local_manifest, remote_manifest) = utils::load_world_manifests( diff --git a/crates/sozo/ops/src/tests/migration.rs b/crates/sozo/ops/src/tests/migration.rs index 50f07a04b3..81847f2bca 100644 --- a/crates/sozo/ops/src/tests/migration.rs +++ b/crates/sozo/ops/src/tests/migration.rs @@ -205,7 +205,7 @@ async fn migration_with_correct_calldata_second_time_work_as_expected() { // adding correct calldata manifest.merge(overlay); } - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let mut world = WorldDiff::compute(manifest, Some(remote_manifest)); world.update_order(&default_namespace).expect("Failed to update order"); @@ -375,7 +375,7 @@ async fn migrate_with_auto_authorize() { let world_address = migration.world_address().expect("must be present"); let world = WorldContract::new(world_address, account); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let res = auto_authorize(&ws, &world, &txn_config, &manifest, &output, &default_namespace).await; assert!(res.is_ok()); @@ -408,7 +408,7 @@ async fn migration_with_mismatching_world_address_and_seed() { let base_dir = config.manifest_path().parent().unwrap().to_path_buf(); let target_dir = base_dir.join("target").join("dev"); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let strategy = prepare_migration_with_world_and_seed( base_dir, diff --git a/crates/sozo/ops/src/tests/setup.rs b/crates/sozo/ops/src/tests/setup.rs index 4ddb0f1459..664ff5e858 100644 --- a/crates/sozo/ops/src/tests/setup.rs +++ b/crates/sozo/ops/src/tests/setup.rs @@ -61,7 +61,7 @@ pub fn setup_migration(config: &Config) -> Result<MigrationStrategy> { let base_dir = manifest_path.parent().unwrap(); let target_dir = format!("{}/target/dev", base_dir); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); prepare_migration_with_world_and_seed( base_dir.into(), diff --git a/crates/torii/core/src/sql_test.rs b/crates/torii/core/src/sql_test.rs index 8477470734..b367eeab61 100644 --- a/crates/torii/core/src/sql_test.rs +++ b/crates/torii/core/src/sql_test.rs @@ -77,7 +77,7 @@ async fn test_load_from_remote() { let base_dir = manifest_path.parent().unwrap(); let target_dir = format!("{}/target/dev", base_dir); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let mut migration = prepare_migration( base_dir.into(), @@ -222,7 +222,7 @@ async fn test_load_from_remote_del() { let base_dir = manifest_path.parent().unwrap(); let target_dir = format!("{}/target/dev", base_dir); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let mut migration = prepare_migration( base_dir.into(), diff --git a/crates/torii/graphql/src/tests/mod.rs b/crates/torii/graphql/src/tests/mod.rs index f9b187c1e8..8bfba50696 100644 --- a/crates/torii/graphql/src/tests/mod.rs +++ b/crates/torii/graphql/src/tests/mod.rs @@ -291,7 +291,7 @@ pub async fn spinup_types_test() -> Result<SqlitePool> { let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let mut migration = prepare_migration( source_project_dir, diff --git a/crates/torii/grpc/src/server/tests/entities_test.rs b/crates/torii/grpc/src/server/tests/entities_test.rs index 8aeb9a0756..205fda416e 100644 --- a/crates/torii/grpc/src/server/tests/entities_test.rs +++ b/crates/torii/grpc/src/server/tests/entities_test.rs @@ -50,7 +50,7 @@ async fn test_entities_queries() { let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); - let default_namespace = get_default_namespace_from_ws(&ws); + let default_namespace = get_default_namespace_from_ws(&ws).unwrap(); let mut migration = prepare_migration( config.manifest_path().parent().unwrap().into(),