Skip to main content

fallow_output/
type_aware_envelopes.rs

1//! Type-aware command output envelopes.
2
3use crate::root_envelopes::serialize_named_json_output;
4use fallow_types::envelope::{SchemaVersion, ToolVersion};
5use serde::Serialize;
6
7/// Current schema version for type-aware status JSON output.
8pub const TYPE_AWARE_STATUS_SCHEMA_VERSION: u32 = 8;
9
10/// Schema projection for the type-aware status envelope's exact version.
11#[cfg(feature = "schema")]
12#[allow(dead_code, reason = "schema-only type used by the field projection")]
13#[derive(schemars::JsonSchema)]
14#[schemars(extend("const" = TYPE_AWARE_STATUS_SCHEMA_VERSION))]
15struct TypeAwareStatusSchemaVersion(u32);
16
17/// Envelope emitted by `fallow type-aware status --format json`.
18#[derive(Debug, Clone, Serialize)]
19#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
20#[cfg_attr(
21    feature = "schema",
22    schemars(title = "fallow type-aware status --format json")
23)]
24pub struct TypeAwareStatusOutput {
25    /// Type-aware status schema version.
26    #[cfg_attr(feature = "schema", schemars(with = "TypeAwareStatusSchemaVersion"))]
27    pub schema_version: SchemaVersion,
28    /// Fallow CLI version that produced this output.
29    pub version: ToolVersion,
30    /// Whether a usable type-aware companion was found.
31    pub available: bool,
32    /// How the companion was discovered, e.g. `installed-sibling`.
33    pub discovery_source: Option<String>,
34    /// Root-relative companion path, or only the executable name when the
35    /// companion lives outside the analyzed project.
36    pub companion_path: Option<String>,
37    /// npm package version of the companion, when known.
38    pub package_version: Option<String>,
39    /// Type-aware protocol version fallow speaks.
40    pub protocol_version: u32,
41    /// Checker backend family, e.g. `typescript-go`.
42    pub backend_family: Option<String>,
43    /// Version of the checker backend, when known.
44    pub backend_version: Option<String>,
45    /// How to make the companion available, when it is not.
46    pub remediation: Option<String>,
47}
48
49/// Serialize the type-aware status envelope with its root discriminator.
50///
51/// # Errors
52///
53/// Returns a serde error when the status output cannot be converted to JSON.
54pub fn serialize_type_aware_status_json_output(
55    output: TypeAwareStatusOutput,
56) -> Result<serde_json::Value, serde_json::Error> {
57    serialize_named_json_output(output, "type-aware-status")
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn status_json_uses_tagged_root_contract() {
66        let value = serialize_type_aware_status_json_output(TypeAwareStatusOutput {
67            schema_version: SchemaVersion(7),
68            version: ToolVersion("3.8.1".to_string()),
69            available: true,
70            discovery_source: Some("installed-sibling".to_string()),
71            companion_path: Some("node_modules/.bin/fallow-type-aware".to_string()),
72            package_version: Some("3.8.1".to_string()),
73            protocol_version: 7,
74            backend_family: Some("typescript-go".to_string()),
75            backend_version: Some("7.0.2".to_string()),
76            remediation: None,
77        })
78        .expect("type-aware status should serialize");
79
80        assert_eq!(value["kind"], "type-aware-status");
81        assert_eq!(
82            value["companion_path"],
83            "node_modules/.bin/fallow-type-aware"
84        );
85    }
86}