qm_entity/ids/
gql.rs

1use std::sync::Arc;
2
3use async_graphql::Description;
4use async_graphql::InputValueError;
5use async_graphql::InputValueResult;
6use async_graphql::OneofObject;
7use async_graphql::Scalar;
8use async_graphql::ScalarType;
9use async_graphql::Value;
10
11use crate::ids::CustomerId;
12use crate::ids::CustomerResourceId;
13use crate::ids::InfraContext;
14use crate::ids::InstitutionId;
15use crate::ids::InstitutionResourceId;
16use crate::ids::OrganizationId;
17use crate::ids::OrganizationResourceId;
18
19#[cfg_attr(
20    feature = "serde-str",
21    derive(serde::Deserialize, serde::Serialize),
22    serde(transparent)
23)]
24pub struct InfraContextId(pub InfraContext);
25
26impl Description for InfraContextId {
27    fn description() -> &'static str {
28        "InfraContextId"
29    }
30}
31
32#[Scalar(use_type_description)]
33impl ScalarType for InfraContextId {
34    fn parse(value: Value) -> InputValueResult<Self> {
35        if let Value::String(value) = &value {
36            // Parse the integer value
37            Ok(InfraContextId(
38                InfraContext::parse(value)
39                    .map_err(|err| InputValueError::custom(err.to_string()))?,
40            ))
41        } else {
42            // If the type does not match
43            Err(InputValueError::expected_type(value))
44        }
45    }
46
47    fn to_value(&self) -> Value {
48        Value::String(self.0.to_string())
49    }
50}
51
52#[macro_export]
53macro_rules! impl_id_scalar {
54    ($t:ty) => {
55        #[Scalar(use_type_description)]
56        impl ScalarType for $t {
57            fn parse(value: Value) -> InputValueResult<Self> {
58                if let Value::String(value) = &value {
59                    // Parse the integer value
60                    Ok(<$t>::parse(value)
61                        .map_err(|err| InputValueError::custom(err.to_string()))?)
62                } else {
63                    // If the type does not match
64                    Err(InputValueError::expected_type(value))
65                }
66            }
67
68            fn to_value(&self) -> Value {
69                Value::String(self.to_string())
70            }
71        }
72    };
73}
74
75impl_id_scalar!(CustomerId);
76impl_id_scalar!(CustomerResourceId);
77impl_id_scalar!(OrganizationId);
78impl_id_scalar!(OrganizationResourceId);
79impl_id_scalar!(InstitutionId);
80impl_id_scalar!(InstitutionResourceId);
81
82#[derive(OneofObject)]
83pub enum CustomerOrOrganization {
84    Customer(CustomerId),
85    Organization(OrganizationId),
86}
87
88#[derive(OneofObject, serde::Serialize, serde::Deserialize)]
89#[serde(tag = "t", content = "c")]
90pub enum OrganizationOrInstitution {
91    Organization(OrganizationId),
92    Institution(InstitutionId),
93}
94
95pub type CustomerIds = Arc<[CustomerId]>;
96pub type CustomerResourceIds = Arc<[CustomerResourceId]>;
97pub type OrganizationIds = Arc<[OrganizationId]>;
98pub type OrganizationResourceIds = Arc<[OrganizationResourceId]>;
99pub type InstitutionIds = Arc<[InstitutionId]>;
100pub type InstitutionResourceIds = Arc<[InstitutionResourceId]>;
101
102#[cfg(test)]
103mod tests {
104    #[cfg(feature = "serde-str")]
105    #[test]
106    fn test_infra_context_id_serde() {
107        use super::{InfraContext, InfraContextId};
108        let infra_context = serde_json::from_str::<InfraContextId>("\"V09\"")
109            .expect("Failed to parse InfraContextId");
110        assert_eq!(infra_context.0, InfraContext::Customer(9.into()));
111        assert_eq!(
112            serde_json::to_string(&infra_context).expect("Failed to serialize InfraContextId"),
113            "\"V09\""
114        );
115    }
116}