Skip to main content

fallow_output/
type_aware_envelopes.rs

1//! Type-aware command output envelopes.
2
3use crate::root_envelopes::{RootEnvelopeMode, 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    mode: RootEnvelopeMode,
57) -> Result<serde_json::Value, serde_json::Error> {
58    serialize_named_json_output(output, "type-aware-status", mode)
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn status_json_uses_tagged_root_contract() {
67        let value = serialize_type_aware_status_json_output(
68            TypeAwareStatusOutput {
69                schema_version: SchemaVersion(7),
70                version: ToolVersion("3.8.1".to_string()),
71                available: true,
72                discovery_source: Some("installed-sibling".to_string()),
73                companion_path: Some("node_modules/.bin/fallow-type-aware".to_string()),
74                package_version: Some("3.8.1".to_string()),
75                protocol_version: 7,
76                backend_family: Some("typescript-go".to_string()),
77                backend_version: Some("7.0.2".to_string()),
78                remediation: None,
79            },
80            RootEnvelopeMode::Tagged,
81        )
82        .expect("type-aware status should serialize");
83
84        assert_eq!(value["kind"], "type-aware-status");
85        assert_eq!(
86            value["companion_path"],
87            "node_modules/.bin/fallow-type-aware"
88        );
89    }
90}