apollo-rs
apollo-rs copied to clipboard
Extend compiler values with custom data types
Description
I'm interested in what the current thinking is on how apollo-compiler
handles custom scalars. Is there any interest in the compiler providing a mechanism for extending the compiler with their custom scalar types (beyond the primitives like String, Int, etc)?
I know the compiler already supports finding custom scalars and the specifiedBy
directive but does not provide any ability to parse/handle scalar types outside of the primitives.
At a high-level I'm thinking that apollo-compiler will expose a trait as an extension point: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=3c1c35224adb1f75486f97d6dfd8812e
use std::collections::HashMap;
use chrono::DateTime;
struct DateScalar {}
struct DateParser {}
struct DateTimeScalar {}
struct DateTimeParser {}
enum CustomScalar {
DateTime(chrono::DateTime<chrono::offset::FixedOffset>),
Date(DateScalar),
}
trait ScalarProvider<T> {
fn parse(&self, input: &str) -> Result<T, Box<dyn std::error::Error>>;
}
impl ScalarProvider<CustomScalar> for DateTimeParser {
fn parse(&self, input: &str) -> Result<CustomScalar, Box<dyn std::error::Error>> {
Ok(CustomScalar::DateTime(DateTime::parse_from_rfc3339(input)?))
}
}
impl ScalarProvider<CustomScalar> for DateParser {
fn parse(&self, input: &str) -> Result<CustomScalar, Box<dyn std::error::Error>> {
Ok(CustomScalar::Date(DateScalar{}))
}
}
The compiler would then provide an interface along the lines of:
compiler.add_custom_scalar_provider(provider);
Then ideally values could be typed by a convenient method like what exists for fields:
// on fields
pub fn ty(&self, db: &dyn HirDatabase) -> Option<Type>
// for arguments: https://docs.rs/apollo-compiler/0.9.2/apollo_compiler/database/hir/struct.Argument.html#method.value
// lookup the primitive value + typename
// try and find a provider for type
// parse and return the highest fidelity version possible for the value (falling back to primitive scalar)
pub fn typed_value(&self, db: &dyn HirDatabase) -> Option<ExtendedValue>