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 Ok(InfraContextId(
38 InfraContext::parse(value)
39 .map_err(|err| InputValueError::custom(err.to_string()))?,
40 ))
41 } else {
42 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 Ok(<$t>::parse(value)
61 .map_err(|err| InputValueError::custom(err.to_string()))?)
62 } else {
63 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}