grafbase_sdk/types/
contract.rs

1use crate::{types::Directive, wit};
2
3/// Represents a GraphQL subgraph with its name and URL.
4pub struct GraphqlSubgraph(wit::GraphqlSubgraph);
5
6impl From<wit::GraphqlSubgraph> for GraphqlSubgraph {
7    fn from(subgraph: wit::GraphqlSubgraph) -> Self {
8        Self(subgraph)
9    }
10}
11
12impl GraphqlSubgraph {
13    /// Name of the subgraph.
14    pub fn name(&self) -> &str {
15        self.0.name.as_str()
16    }
17
18    /// URL of the subgraph.
19    pub fn url(&self) -> &str {
20        self.0.url.as_str()
21    }
22
23    /// Mutable access the URL of the subgraph.
24    pub fn url_mut(&mut self) -> &mut String {
25        &mut self.0.url
26    }
27}
28
29/// Represents a directive associated with a contract.
30#[derive(Clone, Copy)]
31pub struct ContractDirective<'a> {
32    index: u32,
33    directive: Directive<'a>,
34}
35
36impl<'a> From<(usize, &'a wit::Directive)> for ContractDirective<'a> {
37    fn from((index, directive): (usize, &'a wit::Directive)) -> Self {
38        Self {
39            index: index as u32,
40            directive: directive.into(),
41        }
42    }
43}
44
45impl<'a> std::ops::Deref for ContractDirective<'a> {
46    type Target = Directive<'a>;
47    fn deref(&self) -> &Self::Target {
48        &self.directive
49    }
50}
51
52/// Contract that must be applied on the schema.
53pub struct Contract(wit::Contract);
54
55impl Contract {
56    /// Create a new contact with the appropriate capacity which should match the number of
57    /// contract directives.
58    pub fn new(directives: &[ContractDirective<'_>], accessible_by_default: bool) -> Self {
59        Self(wit::Contract {
60            accessible: vec![accessible_by_default as i8 - 1; directives.len()],
61            accessible_by_default,
62            hide_unreachable_types: true,
63            subgraphs: Vec::new(),
64        })
65    }
66
67    /// Set the accessibility of a directive with the lowest priority.
68    pub fn accessible(&mut self, directive: ContractDirective<'_>, accessible: bool) -> &mut Self {
69        let inaccessible_mask = accessible as i8 - 1; // 0xFF if false, 0x00 if true
70        self.accessible_with_priority(directive, (inaccessible_mask & -2) | (!inaccessible_mask & 1))
71    }
72
73    /// Set the accessibility of a directive with the highest priority.
74    pub fn override_accessible(&mut self, directive: ContractDirective<'_>, accessible: bool) -> &mut Self {
75        self.accessible_with_priority(directive, i8::MAX.wrapping_add(!accessible as i8))
76    }
77
78    /// Set the accessibility of a directive with a priority value. The higher the priority, the
79    /// latter this directive will be taken into account, overriding any previous ones.
80    ///
81    /// A positive value indicates that the directive is accessible, so `[0, 127]` means accessible
82    /// but `[-128, -1]` doesn't. The absolute value is used as the priority after shifting the
83    /// positive values up by one. So both `-1` and `0` have the same priority, `-2` and `1` also
84    /// and so forth up to `-128` and `127`.
85    ///
86    /// The default behavior is encoded as `-1` and `0`, so to override the default accessibility
87    /// of the contract, you must use at least `-2` or `1`.
88    pub fn accessible_with_priority(&mut self, directive: ContractDirective<'_>, accessible: i8) -> &mut Self {
89        self.0.accessible[directive.index as usize] = accessible;
90        self
91    }
92
93    /// Whether to hide types that are not reachable from the root type. Defaults to true.
94    pub fn hide_unreachable_types(&mut self, hide: bool) -> &mut Self {
95        self.0.hide_unreachable_types = hide;
96        self
97    }
98
99    /// Add a subgraph update to the subgraph. Unchanged subgraph do not need to be provided.
100    /// The number of subgraphs and their name cannot be changed.
101    pub fn subgraph(&mut self, subgraph: GraphqlSubgraph) -> &mut Self {
102        self.0.subgraphs.push(subgraph.0);
103        self
104    }
105}
106
107impl From<Contract> for wit::Contract {
108    fn from(contract: Contract) -> Self {
109        contract.0
110    }
111}