-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Making scalar coercion more powerful
It would be a huge advantage to be able to access the context during serializing/deserializing scalars. It would allow to reduce a lot of additional type conversion that must happen in data fetchers on input and output because it requires some contextual information.
Use cases:
Converting date time to client's time zone
Some applications need to be aware of the current user time zone. This is for example necessary when aggregating calendar events into dates. It just cannot be done in UTC.
The application could internally work with java.time.Instant. During the conversion from the literal to Java type the context object could provide the current client time-zone and convert it to the correct Instant thus keeping the conversion logic in one place.
GraphQLScalarType
.newScalar()
.name("DateTime")
.coercing(new Coercing<Instant, String>() {
@Override
public String serialize(Object instant, Context context) {
if (instant instanceof Instant) {
((Instant) instant).atZone(context.getZoneId()).toString();
}
// throw
}
@Override
public Instant parseValue(Object input, Context context) {
LocalDateTime.parse(input).atZone(context.getZoneId).toInstant();
}
})
.build();Translating strings into client's locale
Similarly, Strings could be translated on output by using a special type internally MessageBundleKey and converting it to GraphQL string in the coercion. By being able to access the context it would be possible to determine the client locale and translate the message bundle key type into GraphQL string in the correct language.
GraphQLScalarType
.newScalar()
.name("LocalizedString")
.coercing(new Coercing<MessageBundleKey, String>() {
@Override
public String serialize(Object key, Context context) {
return messageBundle.getMessage(key, context.getLocale());
}
})
.build();Workaround
The only current workaround is to inject the context in a different way. For example using thread local global variables. Spring already offers a similar mechanism using the LocaleContextHolder class. The disadvantage is that it relies on the fact that each thread has a separate context which is not true in a reactive app or when using subscriptions.