-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
feature_flags.rs
148 lines (120 loc) · 4.94 KB
/
feature_flags.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use indexmap::IndexSet;
use intern::string_key::StringKey;
use intern::Lookup;
use serde::Deserialize;
use serde::Serialize;
use crate::Rollout;
#[derive(Default, Debug, Serialize, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct FeatureFlags {
#[serde(default)]
pub enable_relay_resolver_transform: bool,
/// Enable deprecated `@outputType` on Relay Resolvers.
#[serde(default)]
pub relay_resolver_enable_output_type: FeatureFlag,
#[serde(default)]
// Enable returning interfaces from Relay Resolvers without @outputType
pub relay_resolver_enable_interface_output_type: FeatureFlag,
/// For now, this also disallows fragments with variable definitions
/// This also makes @module to opt in using @no_inline internally
/// NOTE that the presence of a fragment in this list only controls whether a fragment is *allowed* to
/// use @no_inline: whether the fragment is inlined or not depends on whether it actually uses that
/// directive.
#[serde(default)]
pub no_inline: FeatureFlag,
#[serde(default)]
pub enable_3d_branch_arg_generation: bool,
#[serde(default)]
pub actor_change_support: FeatureFlag,
/// Enable generation of text artifacts used to generate full query strings
/// later.
#[serde(default)]
pub text_artifacts: FeatureFlag,
#[serde(default)]
pub skip_printing_nulls: FeatureFlag,
/// Enable support for the experimental `@alias` directive on fragment spreads.
#[serde(default)]
pub enable_fragment_aliases: FeatureFlag,
/// Print queries in compact form
#[serde(default)]
pub compact_query_text: FeatureFlag,
/// Create normalization nodes for client edges to client objects
#[serde(default)]
pub emit_normalization_nodes_for_client_edges: bool,
/// Fully build the normalization AST for Resolvers
#[serde(default)]
pub enable_resolver_normalization_ast: bool,
/// Enforce strict flavors for relay resolvers and disallow mixing flavors
#[serde(default)]
pub relay_resolvers_enable_strict_resolver_flavors: FeatureFlag,
/// Allow legacy verbose resolver syntax
#[serde(default)]
pub relay_resolvers_allow_legacy_verbose_syntax: FeatureFlag,
/// Allow relay resolvers to extend the Mutation type
#[serde(default)]
pub enable_relay_resolver_mutations: bool,
/// Perform strict validations when custom scalar types are used
#[serde(default)]
pub enable_strict_custom_scalars: bool,
/// Relay Resolvers are a read-time feature that are not actually handled in
/// our mutation APIs. We are in the process of removing any existing
/// examples, but this flag is part of a process of removing any existing
/// examples.
#[serde(default)]
pub allow_resolvers_in_mutation_response: FeatureFlag,
/// @required with an action of THROW is read-time feature that is not
/// compatible with our mutation APIs. We are in the process of removing
/// any existing examples, but this flag is part of a process of removing
/// any existing examples.
#[serde(default)]
pub allow_required_in_mutation_response: FeatureFlag,
}
#[derive(Debug, Deserialize, Clone, Serialize, Default)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum FeatureFlag {
/// Fully disabled: developers may not use this feature
#[default]
Disabled,
/// Fully enabled: developers may use this feature
Enabled,
/// Partially enabled: developers may only use this feature on the listed items (fragments, fields, types).
Limited { allowlist: IndexSet<StringKey> },
/// Partially enabled: used for gradual rollout of the feature
Rollout { rollout: Rollout },
}
impl FeatureFlag {
pub fn is_enabled_for(&self, name: StringKey) -> bool {
match self {
FeatureFlag::Enabled => true,
FeatureFlag::Limited { allowlist } => allowlist.contains(&name),
FeatureFlag::Rollout { rollout } => rollout.check(name.lookup()),
FeatureFlag::Disabled => false,
}
}
pub fn is_fully_enabled(&self) -> bool {
matches!(self, FeatureFlag::Enabled)
}
}
impl Display for FeatureFlag {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
FeatureFlag::Disabled => f.write_str("disabled"),
FeatureFlag::Enabled => f.write_str("enabled"),
FeatureFlag::Limited { allowlist } => {
let items: Vec<_> = allowlist.iter().map(|x| x.lookup()).collect();
f.write_str("limited to: ")?;
f.write_str(&items.join(", "))
}
FeatureFlag::Rollout { rollout } => write!(f, "Rollout: {:#?}", rollout),
}
}
}