1use crate::braze::error::BrazeApiError;
7use crate::braze::BrazeClient;
8use crate::config::ResolvedConfig;
9use crate::fs::catalog_io;
10use crate::resource::ResourceKind;
11use anyhow::Context as _;
12use clap::Args;
13use std::path::Path;
14
15use super::{selected_kinds, warn_unimplemented};
16
17#[derive(Args, Debug)]
18pub struct ExportArgs {
19 #[arg(long, value_enum)]
22 pub resource: Option<ResourceKind>,
23
24 #[arg(long, requires = "resource")]
27 pub name: Option<String>,
28}
29
30pub async fn run(
31 args: &ExportArgs,
32 resolved: ResolvedConfig,
33 config_dir: &Path,
34) -> anyhow::Result<()> {
35 let catalogs_root = config_dir.join(&resolved.resources.catalog_schema.path);
36 let client = BrazeClient::from_resolved(&resolved);
37 let kinds = selected_kinds(args.resource, &resolved.resources);
38
39 let mut total_written: usize = 0;
40 for kind in kinds {
41 match kind {
42 ResourceKind::CatalogSchema => {
43 let n = export_catalog_schemas(&client, &catalogs_root, args.name.as_deref())
44 .await
45 .context("exporting catalog_schema")?;
46 eprintln!("✓ catalog_schema: exported {n} resource(s)");
47 total_written += n;
48 }
49 other => {
50 warn_unimplemented(other);
51 }
52 }
53 }
54
55 eprintln!("done: {total_written} resource(s) written");
56 Ok(())
57}
58
59async fn export_catalog_schemas(
60 client: &BrazeClient,
61 catalogs_root: &Path,
62 name_filter: Option<&str>,
63) -> anyhow::Result<usize> {
64 let catalogs = match name_filter {
65 Some(name) => match client.get_catalog(name).await {
66 Ok(c) => vec![c],
67 Err(BrazeApiError::NotFound { .. }) => {
70 eprintln!("⚠ catalog_schema: '{name}' not found in Braze");
71 Vec::new()
72 }
73 Err(e) => return Err(e.into()),
74 },
75 None => client.list_catalogs().await?,
76 };
77
78 let count = catalogs.len();
79 for cat in catalogs {
80 catalog_io::save_schema(catalogs_root, &cat)?;
81 }
82 Ok(count)
83}