Skip to main content

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