graphql / graphql/graphql-spec

Clarify allowed Values for Scalar types

Open
#688 11 comments 0 reactions 0 assignees View on GitHub
🤷‍♀️ Ambiguity
Dominant language
JavaScript
Stars
14.6k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

The spec makes no statement about what GraphQL input values are valid for a custom `Scalar` value.

-------

Let's take an `IntRange` type for example:
- It always has exactly two `Int!` values: `start` end `endInclusive`.
- The typical approach for a type with multiple properties would be to create a `type IntRange` with two `Int!` fields for output, and an `input IntRangeInput` with the same two fields for input.

That's unnecessary for such a simple type, so I'd love to represent it as a `Scalar` instead. But because the type comprised of two values it cannot be represented by any other built-in `Scalar` type except `String`. The latter would require a custom serialization format like `"start...endInclusive"`.

According to the spec `Scalar` represents **primitive** values.
> The most basic type is a `Scalar`. A scalar represents a primitive value, like a string or an integer.

The spec doesn't really say what **primitive** means.

---------

My idea is now to simply use a custom `Scalar` with an object representation for input and output.

Output it's simple because the spec basically allows any format:

> GraphQL scalars are serialized according to the serialization format being used. There may be a most appropriate serialized primitive for each given scalar type, and the server should produce each primitive where appropriate.

So I can use a JSON object:
```json
{ "start": 1, "endInclusive": 10 }
```

Input coercing for custom scalars isn't defined beyond the following:
> If a GraphQL server expects a scalar type as input to an argument, coercion is observable and the rules must be well defined. If an input value does not match a coercion rule, a query error must be raised.

Basically the server can accept any value it wants to as long as it clearly defines that. That theoretically allows for using an [`ObjectValue`](https://spec.graphql.org/draft/#ObjectValue) to represent a `scalar IntRange`:

```graphql
{ start: 1, endInclusive: 10 }
```

### Conclusion

Something like `IntRange` could be seen as a primitive and thus be implemented as a `Scalar`. It could be represented using a JSON object for output and variable input, and as [`ObjectValue`](https://spec.graphql.org/draft/#ObjectValue) for input in a GraphQL document.

**However in the spec it is not clear whether that is acceptable or not.**
Theoretically that approach can collide with the [Input Object Field Names](https://spec.graphql.org/draft/#sec-Input-Object-Field-Names) validation.

I suggest to clearly define what [`Value`](https://spec.graphql.org/draft/#Value)s are valid to use for a `Scalar`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.