use crate::{
component::AnyExtension,
types::{
AuthorizedOperationContext, Configuration, Error, IndexedSchema, ResolvedField, Response, SubgraphHeaders,
SubgraphSchema, SubscriptionItem, Variables,
},
};
pub trait ResolverExtension: Sized + 'static {
fn new(subgraph_schemas: Vec<SubgraphSchema>, config: Configuration) -> Result<Self, Error>;
fn prepare(&mut self, field: ResolvedField<'_>) -> Result<Vec<u8>, Error> {
Ok(field.into())
}
fn resolve(
&mut self,
ctx: &AuthorizedOperationContext,
prepared: &[u8],
headers: SubgraphHeaders,
variables: Variables,
) -> Result<Response, Error>;
#[allow(unused_variables)]
fn resolve_subscription<'s>(
&'s mut self,
ctx: &'s AuthorizedOperationContext,
prepared: &'s [u8],
headers: SubgraphHeaders,
variables: Variables,
) -> Result<impl IntoSubscription<'s>, Error> {
unimplemented!("Subscription resolution not implemented for this resolver extension");
#[allow(unused)]
Ok(PhantomSubscription)
}
}
pub trait Subscription {
fn next(&mut self) -> Result<Option<SubscriptionItem>, Error>;
}
pub type SubscriptionCallback<'s> = Box<dyn FnOnce() -> Result<Box<dyn Subscription + 's>, Error> + 's>;
pub trait IntoSubscription<'s> {
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>);
}
impl<'s, S> IntoSubscription<'s> for S
where
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(None, Box::new(move || Ok(Box::new(self))))
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Vec<u8>, Callback)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(
Some(self.0),
Box::new(move || {
let s = (self.1)()?;
Ok(Box::new(s) as Box<dyn Subscription + 's>)
}),
)
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Option<Vec<u8>>, Callback)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(
self.0,
Box::new(move || {
let s = (self.1)()?;
Ok(Box::new(s) as Box<dyn Subscription + 's>)
}),
)
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (String, Callback)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(
Some(self.0.into()),
Box::new(move || {
let s = (self.1)()?;
Ok(Box::new(s) as Box<dyn Subscription + 's>)
}),
)
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Option<String>, Callback)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(
self.0.map(Into::into),
Box::new(move || {
let s = (self.1)()?;
Ok(Box::new(s) as Box<dyn Subscription + 's>)
}),
)
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Callback, Vec<u8>)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(self.1, self.0).into_deduplication_key_and_subscription_callback()
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Callback, Option<Vec<u8>>)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(self.1, self.0).into_deduplication_key_and_subscription_callback()
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Callback, String)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(self.1, self.0).into_deduplication_key_and_subscription_callback()
}
}
impl<'s, Callback, S> IntoSubscription<'s> for (Callback, Option<String>)
where
Callback: FnOnce() -> Result<S, Error> + 's,
S: Subscription + 's,
{
fn into_deduplication_key_and_subscription_callback(self) -> (Option<Vec<u8>>, SubscriptionCallback<'s>) {
(self.1, self.0).into_deduplication_key_and_subscription_callback()
}
}
#[doc(hidden)]
pub fn register<T: ResolverExtension>() {
pub(super) struct Proxy<T: ResolverExtension>(T);
impl<T: ResolverExtension> AnyExtension for Proxy<T> {
fn prepare(&mut self, field: ResolvedField<'_>) -> Result<Vec<u8>, Error> {
self.0.prepare(field)
}
fn resolve(
&mut self,
ctx: &AuthorizedOperationContext,
prepared: &[u8],
headers: SubgraphHeaders,
variables: Variables,
) -> Response {
self.0.resolve(ctx, prepared, headers, variables).into()
}
fn resolve_subscription<'a>(
&'a mut self,
ctx: &'a AuthorizedOperationContext,
prepared: &'a [u8],
headers: SubgraphHeaders,
variables: Variables,
) -> Result<(Option<Vec<u8>>, SubscriptionCallback<'a>), Error> {
let (key, callback) = self
.0
.resolve_subscription(ctx, prepared, headers, variables)?
.into_deduplication_key_and_subscription_callback();
Ok((key, callback))
}
}
crate::component::register_extension(Box::new(|subgraph_schemas, config| {
let schemas = subgraph_schemas
.into_iter()
.map(IndexedSchema::from)
.collect::<Vec<_>>();
<T as ResolverExtension>::new(schemas.into_iter().map(SubgraphSchema).collect(), config)
.map(|extension| Box::new(Proxy(extension)) as Box<dyn AnyExtension>)
}))
}
struct PhantomSubscription;
impl Subscription for PhantomSubscription {
fn next(&mut self) -> Result<Option<SubscriptionItem>, Error> {
Ok(None) }
}