es_fluent_cli_helpers/
cli.rs

1//! Inventory collection functionality for CLI commands.
2
3use serde::Serialize;
4use std::collections::{HashMap, HashSet};
5
6/// Expected key information from inventory.
7#[derive(Serialize)]
8pub struct ExpectedKey {
9    pub key: String,
10    pub variables: Vec<String>,
11}
12
13/// The inventory data output.
14#[derive(Serialize)]
15pub struct InventoryData {
16    pub expected_keys: Vec<ExpectedKey>,
17}
18
19/// Collects inventory data for a crate and writes it to `inventory.json`.
20///
21/// This function is used by the es-fluent CLI to collect expected FTL keys
22/// and their variables from inventory-registered types.
23///
24/// # Arguments
25///
26/// * `crate_name` - The name of the crate to collect inventory for (e.g., "my-crate")
27///
28/// # Panics
29///
30/// Panics if serialization or file writing fails.
31pub fn write_inventory_for_crate(crate_name: &str) {
32    let crate_ident = crate_name.replace('-', "_");
33
34    // Collect all registered type infos for this crate
35    let type_infos: Vec<_> = es_fluent_core::registry::get_all_ftl_type_infos()
36        .into_iter()
37        .filter(|info| {
38            info.module_path == crate_ident
39                || info.module_path.starts_with(&format!("{}::", crate_ident))
40        })
41        .collect();
42
43    // Build a map of expected keys and their required variables (deduplicated)
44    let mut keys_map: HashMap<String, HashSet<String>> = HashMap::new();
45    for info in &type_infos {
46        for variant in &info.variants {
47            let key = variant.ftl_key.0.clone();
48            let vars: HashSet<String> = variant.args.iter().cloned().collect();
49            keys_map.entry(key).or_default().extend(vars);
50        }
51    }
52
53    // Convert to output format
54    let expected_keys: Vec<ExpectedKey> = keys_map
55        .into_iter()
56        .map(|(key, vars)| ExpectedKey {
57            key,
58            variables: vars.into_iter().collect(),
59        })
60        .collect();
61
62    let data = InventoryData { expected_keys };
63
64    // Write inventory data to file
65    let json = serde_json::to_string(&data).expect("Failed to serialize inventory data");
66
67    let metadata_dir = std::path::Path::new("metadata").join(crate_name);
68    std::fs::create_dir_all(&metadata_dir).expect("Failed to create metadata directory");
69
70    std::fs::write(metadata_dir.join("inventory.json"), json)
71        .expect("Failed to write inventory file");
72}