@@ -0,0 +1,92 @@
1+# Scalar Types
2+
3+## Leaf Types
4+
5+In GraphQL, Leaf Types are types that turn into a specific value and have no connections to other types (other than their parent node).
6+There are two GraphQL kinds that can produce leaf types: The Scalar and the Enumeration.
7+Enum types are used for types that have a finite set of values and serialize by mapping to a finite set of JSON string values.
8+Scalar types, on the other hand, can serialize to any JSON value.
9+This includes JSON lists and maps, but usually scalars should use the JSON primitive types for representation: String, Number, Boolean.
10+
11+## Built in Scalar Types
12+
13+The GraphQL Specification lists five scalar types, that need to be supported by every GraphQL implementation.
14+These scalars are probably enough to get you started in your project.
15+
16+- The `Int` scalar is used for [natural numbers in the Int32 range](http://spec.graphql.org/June2018/#sec-Int).
17+- The `Float` type represents [signed double‐precision fractional values](http://spec.graphql.org/June2018/#sec-Float).
18+- The `String` scalar represents [UTF-8 encoded strings](http://spec.graphql.org/June2018/#sec-String).
19+- The `Boolean` scalar represents [boolean logic truth values](http://spec.graphql.org/June2018/#sec-Boolean).
20+- And finally the `ID` scalar is used for [unique identifiers](http://spec.graphql.org/June2018/#sec-ID). It is always serialised as a JSON string, but can also accept integer values from client queries.
21+
22+PureScript GraphQL provides implementations for these scalars in the `GraphQL.Builtin.Scalar` module.
23+As GraphQL types are values in PureScript, they use lower case identifiers: `int`, `float`, `string`, `boolean` and `id`.
24+They are exported as well from the `GraphQL` main module.
25+
26+## Defining custom Scalar Types
27+
28+Sometimes, the built in scalar types are not enough and you want to represent a custom type together with input validation.
29+One great example is the `DateTime` scalar.
30+
31+> **Note:**
32+> You can find the full code for this example [here](https://github.com/hendrikniemann/purescript-graphql-fullstack-example/blob/master/backend/src/Schema/DateTime.purs).
33+
34+The predefined scalars are using the `ScalarType` newtype to implement the serialization and deserialization logic.
35+We can do the same to provide our own custom scalars.
36+If we want to build a scalar that serializes `DateTime` from `Data.DateTime` into a string in ISO 8601 format (`YYYY-MM-DDTHH:mm:ss.SSSZ`), we have to provide two functions:
37+
38+- `parseDateTime` which takes a string and returns either an error message or a valid `DateTime`.
39+- `formatDateTime` which turns a `DateTime` into a string.
40+
41+Using `Data.Formatter.DateTime`, we can easily write these functions:
42+
43+```purescript
44+parseDateTime :: String -> Either String DateTime
45+parseDateTime = unformat dateFormat
46+
47+formatDateTime :: DateTime -> String
48+formatDateTime = format dateFormat
49+
50+dateFormat ∷ Formatter
51+dateFormat = parseFormatString "YYYY-MM-DDTHH:mm:ss.SSSZ" # unsafePartial fromRight
52+```
53+
54+With these two helper functions we can now implement the functions needed by the scalar:
55+
56+### `parseLiteral`
57+
58+`parseLiteral` is called when the scalar is used in an argument in a query and the value is supplied inline as a literal.
59+Here we have to deal with the different literal types that exist in GraphQL.
60+In our case we only want to accept `StringValueNode`s and error on everything else.
61+We can then parse the value using the `parseDateTime` function above.
62+
63+```purescript
64+parseLiteral (AST.StringValueNode { value }) = parseDateTime value
65+parseLiteral _ = Left "Expected string literal node for input type date time."
66+```
67+
68+> Usually types only work for a single type of literal but it is totally possible to parse different types of literals if you want to do so.
69+> It can also be an opportunity to implement more specific error messages.
70+
71+### `parseValue`
72+
73+`parseValue` is called whenever a variable of our scalar type is supplied.
74+In this case we have to react to a JSON value. This is easy with _Argonaut_:
75+
76+```purescript
77+parseValue = Json.caseJsonString (Left "Dates must be supplied as ISO strings.") parseDateTime
78+```
79+
80+### `serialize`
81+
82+In `serialize` we have to do the opposite:
83+Turn a `DateTime` value into a JSON value.
84+Again, we are using _Argonaut_ and our helper function `formatDateTime` to compose the final function.
85+
86+```purescript
87+serialize = formatDateTime >>> Json.fromString
88+```
89+
90+!> Scalars in PureScript are designed to be as typesafe and pure as possible.
91+Therefore `serialize` is not allowed to have side effects or return an error.
92+All potential errors must be dealt with in the field resolver.