Files
axum-async-graphql/src/scalar.rs

71 lines
2.1 KiB
Rust
Raw Normal View History

2026-06-04 22:42:57 +02:00
use async_graphql::*;
2026-06-06 11:59:20 +02:00
use sqlx::{
postgres::{PgArgumentBuffer, PgHasArrayType, PgTypeInfo, PgValueRef},
Decode, Encode, Postgres, Type,
};
use ulid::Ulid as UlidPrimitive;
pub type Time = chrono::DateTime<chrono::Utc>;
/// The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache.
/// The ID type appears in a JSON response as a String; however, it is not intended to be human-readable.
/// When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID.
2026-06-06 11:59:20 +02:00
pub type Id = uuid::Uuid;
2026-06-04 22:42:57 +02:00
2026-06-06 11:59:20 +02:00
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Ulid(pub UlidPrimitive);
2026-06-04 22:42:57 +02:00
#[Scalar]
impl ScalarType for Ulid {
fn parse(value: Value) -> InputValueResult<Self> {
match value {
Value::String(s) => {
2026-06-06 11:59:20 +02:00
let ulid = UlidPrimitive::from_string(&s).map_err(InputValueError::custom)?;
2026-06-04 22:42:57 +02:00
Ok(Ulid(ulid))
}
_ => Err(InputValueError::expected_type(value)),
}
}
fn to_value(&self) -> Value {
Value::String(self.0.to_string())
}
}
impl Type<Postgres> for Ulid {
fn type_info() -> PgTypeInfo {
2026-06-06 11:59:20 +02:00
<String as Type<Postgres>>::type_info()
2026-06-04 22:42:57 +02:00
}
2026-06-06 11:59:20 +02:00
2026-06-04 22:42:57 +02:00
fn compatible(ty: &PgTypeInfo) -> bool {
<String as Type<Postgres>>::compatible(ty)
}
}
2026-06-06 11:59:20 +02:00
2026-06-04 22:42:57 +02:00
impl<'r> Decode<'r, Postgres> for Ulid {
fn decode(value: PgValueRef<'r>) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
let s = <String as Decode<Postgres>>::decode(value)?;
2026-06-06 11:59:20 +02:00
Ok(Ulid(UlidPrimitive::from_string(s.trim())?))
2026-06-04 22:42:57 +02:00
}
}
impl<'q> Encode<'q, Postgres> for Ulid {
fn encode_by_ref(
&self,
buf: &mut PgArgumentBuffer,
) -> Result<sqlx::encode::IsNull, Box<dyn std::error::Error + Send + Sync>> {
<String as Encode<Postgres>>::encode(self.0.to_string(), buf)
}
}
2026-06-06 11:59:20 +02:00
2026-06-04 22:42:57 +02:00
impl PgHasArrayType for Ulid {
fn array_type_info() -> PgTypeInfo {
2026-06-06 11:59:20 +02:00
<String as PgHasArrayType>::array_type_info()
2026-06-04 22:42:57 +02:00
}
fn array_compatible(ty: &PgTypeInfo) -> bool {
<String as PgHasArrayType>::array_compatible(ty)
}
2026-06-04 22:42:57 +02:00
}