settings.rs

 1use collections::HashMap;
 2use schemars::{Schema, json_schema};
 3use serde_json::{Map, Value};
 4use settings::{RegisterSetting, Settings, SettingsContent};
 5
 6use crate::FeatureFlagStore;
 7
 8#[derive(Clone, Debug, Default, RegisterSetting)]
 9pub struct FeatureFlagsSettings {
10    pub overrides: HashMap<String, String>,
11}
12
13impl Settings for FeatureFlagsSettings {
14    fn from_settings(content: &SettingsContent) -> Self {
15        Self {
16            overrides: content
17                .feature_flags
18                .as_ref()
19                .map(|map| map.0.clone())
20                .unwrap_or_default(),
21        }
22    }
23}
24
25/// Produces a JSON schema for the `feature_flags` object that lists each known
26/// flag as a property with its variant keys as an `enum`.
27///
28/// Unknown flags are permitted via `additionalProperties: { "type": "string" }`,
29/// so removing a flag from the binary never turns existing entries in
30/// `settings.json` into validation errors.
31pub fn generate_feature_flags_schema() -> Schema {
32    let mut properties = Map::new();
33
34    for descriptor in FeatureFlagStore::known_flags() {
35        let variants = (descriptor.variants)();
36        let enum_values: Vec<Value> = variants
37            .iter()
38            .map(|v| Value::String(v.override_key.to_string()))
39            .collect();
40        let enum_descriptions: Vec<Value> = variants
41            .iter()
42            .map(|v| Value::String(v.label.to_string()))
43            .collect();
44
45        let mut property = Map::new();
46        property.insert("type".to_string(), Value::String("string".to_string()));
47        property.insert("enum".to_string(), Value::Array(enum_values));
48        // VS Code / json-language-server use `enumDescriptions` for hover docs
49        // on each enum value; schemars passes them through untouched.
50        property.insert(
51            "enumDescriptions".to_string(),
52            Value::Array(enum_descriptions),
53        );
54        property.insert(
55            "description".to_string(),
56            Value::String(format!(
57                "Override for the `{}` feature flag. Default: `{}` (the {} variant).",
58                descriptor.name,
59                (descriptor.default_variant_key)(),
60                (descriptor.default_variant_key)(),
61            )),
62        );
63
64        properties.insert(descriptor.name.to_string(), Value::Object(property));
65    }
66
67    json_schema!({
68        "type": "object",
69        "description": "Local overrides for feature flags, keyed by flag name.",
70        "properties": properties,
71        "additionalProperties": {
72            "type": "string",
73            "description": "Unknown feature flag; retained so removed flags don't trip settings validation."
74        }
75    })
76}