wowlab_engine/cli/
resolver.rs1use wowlab_engine_ports::DynDataResolver;
2use wowlab_fs::{
3 directory::{self, EntryKind},
4 path::{Path, PathBuf},
5};
6
7use super::CliError;
8
9pub(super) struct ResolverHandle {
10 pub resolver: Box<DynDataResolver<'static>>,
11 pub source: String,
12}
13
14pub(super) fn create(workspace_root: &Path) -> Result<ResolverHandle, CliError> {
15 #[cfg(feature = "supabase")]
16 {
17 if std::env::var("SUPABASE_URL").is_ok() {
18 let patch = std::env::var("WOWLAB_PATCH")
19 .unwrap_or_else(|_| wowlab_types::constants::DEFAULT_WOW_PATCH.to_string());
20
21 match create_supabase(&patch) {
22 Ok(resolver) => {
23 return Ok(ResolverHandle {
24 resolver: DynDataResolver::new_box(resolver),
25 source: "supabase".to_string(),
26 });
27 }
28 Err(e) => {
29 tracing::warn!(error = %e, "Supabase initialization failed; using local data");
30 }
31 }
32 }
33 }
34
35 let data_dir = local_data_dir(workspace_root)?;
36 let source = format!("local ({data_dir})");
37
38 Ok(ResolverHandle {
39 resolver: DynDataResolver::new_box(wowlab_engine_adapter_data::LocalCsvResolver::new(
40 data_dir,
41 )),
42 source,
43 })
44}
45
46#[cfg(feature = "supabase")]
47fn create_supabase(patch: &str) -> Result<wowlab_engine_adapter_data::SupabaseResolver, CliError> {
48 let client = wowlab_supabase::SupabaseClient::from_env()?;
49 let cache_dir = wowlab_common::config_dir(
50 "WOWLAB",
51 wowlab_common::ProjectIdentity {
52 qualifier: "gg",
53 organization: "wowlab",
54 application: "wowlab-engine",
55 },
56 )
57 .map(|directory| directory.join("game-data"))
58 .ok_or_else(|| {
59 CliError::resolver(
60 "game-data cache directory is unavailable; set WOWLAB_CONFIG_DIR".to_string(),
61 )
62 })?;
63 let cache = wowlab_engine_adapter_data::GameDataCache::new(client, patch, cache_dir)?;
64
65 Ok(wowlab_engine_adapter_data::SupabaseResolver::new(cache))
66}
67
68fn local_data_dir(workspace_root: &Path) -> Result<PathBuf, CliError> {
69 let data_dir = match std::env::var("WOWLAB_DATA_DIR") {
70 Ok(dir) => PathBuf::from(dir),
71 Err(_) => default_data_dir(workspace_root).ok_or_else(|| {
72 CliError::resolver(
73 "could not derive the default game-data directory from the repo root. \
74 Set WOWLAB_DATA_DIR to a local game-data directory"
75 .to_string(),
76 )
77 })?,
78 };
79
80 if !directory::inspect(&data_dir)?.is_some_and(|entry| entry.kind() == EntryKind::Directory) {
81 return Err(CliError::resolver(format!(
82 "game-data directory '{data_dir}' does not exist. \
83 Set WOWLAB_DATA_DIR to a valid local game-data directory"
84 )));
85 }
86
87 Ok(data_dir)
88}
89
90fn default_data_dir(workspace_root: &Path) -> Option<PathBuf> {
91 workspace_root.parent().map(|root| root.join("wowlab-data"))
92}