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}