Skip to main content

faucet_cli/commands/
schema.rs

1//! `faucet schema` — print the JSON Schema for a connector's config.
2
3use crate::cli::{SchemaArgs, SchemaTarget};
4use crate::error::CliResult;
5use crate::registry::{sink_schema, source_schema};
6use crate::transforms::transform_schema;
7
8/// Execute the `schema` subcommand.
9pub async fn run(args: SchemaArgs) -> CliResult<()> {
10    let schema = match args.target {
11        SchemaTarget::Source { name } => source_schema(&name)?,
12        SchemaTarget::Sink { name } => sink_schema(&name)?,
13        SchemaTarget::Transform { name } => transform_schema(&name)?,
14        SchemaTarget::Dlq => {
15            let dlq_schema = faucet_core::schema_for!(crate::config::DlqSpec);
16            serde_json::to_value(dlq_schema)
17                .unwrap_or_else(|_| serde_json::json!({"type": "object"}))
18        }
19        #[cfg(feature = "quality")]
20        SchemaTarget::Quality => {
21            let quality_schema = faucet_core::schema_for!(faucet_core::QualitySpec);
22            serde_json::to_value(quality_schema)
23                .unwrap_or_else(|_| serde_json::json!({"type": "object"}))
24        }
25        #[cfg(feature = "schedule")]
26        SchemaTarget::Schedule => {
27            let s = faucet_core::schema_for!(crate::schedule::spec::ScheduleSpec);
28            serde_json::to_value(s).unwrap_or_else(|_| serde_json::json!({"type": "object"}))
29        }
30        #[cfg(feature = "lineage")]
31        SchemaTarget::Lineage => lineage_schema(),
32        #[cfg(feature = "triggers")]
33        SchemaTarget::Triggers => {
34            let s = faucet_core::schema_for!(crate::serve::triggers::spec::TriggersFile);
35            serde_json::to_value(s).unwrap_or_else(|_| serde_json::json!({"type": "object"}))
36        }
37        SchemaTarget::Secrets => serde_json::json!({
38            "title": "Secrets-manager interpolation grammar",
39            "schemes": {
40                "vault":    { "syntax": "${vault:<path>[#field]}", "auth": ["VAULT_ADDR", "VAULT_TOKEN", "VAULT_NAMESPACE (optional)"] },
41                "aws-sm":   { "syntax": "${aws-sm:<name-or-ARN>[#field]}", "auth": ["aws-config default credential chain"] },
42                "gcp-sm":   { "syntax": "${gcp-sm:projects/<p>/secrets/<s>/versions/<v>}", "auth": ["Application Default Credentials"] },
43                "azure-kv": { "syntax": "${azure-kv:<vault>/<secret>[/<version>]}", "auth": ["AZURE_* env / managed identity / az login"] }
44            },
45            "notes": [
46                "#field parses the secret as JSON and extracts one key (vault, aws-sm).",
47                "Resolved at config load; fetched concurrently and de-duplicated; never persisted.",
48                "Build with --features secrets (or per-backend secrets-vault / secrets-aws-sm / ...)."
49            ]
50        }),
51    };
52    let body = serde_json::to_string_pretty(&schema).unwrap_or_else(|_| schema.to_string());
53    println!("{body}");
54    Ok(())
55}
56
57/// JSON Schema for the `lineage:` config block (`faucet schema lineage`).
58#[cfg(feature = "lineage")]
59pub fn lineage_schema() -> serde_json::Value {
60    serde_json::to_value(faucet_lineage::schemars_schema())
61        .unwrap_or_else(|_| serde_json::json!({"type": "object"}))
62}
63
64#[cfg(test)]
65mod tests {
66    #[cfg(feature = "lineage")]
67    #[test]
68    fn schema_lineage_returns_object_schema() {
69        let v = super::lineage_schema();
70        assert_eq!(v["type"], "object");
71        assert!(v["properties"].get("transport").is_some());
72        assert!(v["properties"].get("namespace").is_some());
73    }
74}