fixes scalars and variable coercion documentation

This commit is contained in:
jangko 2021-04-17 12:43:45 +07:00
parent 2242dc6dcc
commit 942a06c11e
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 75 additions and 1 deletions

View File

@ -3,7 +3,7 @@
```Nim
type
NodeResult* = Result[Node, string]
CoerceProc* = proc(ctx: Graphql, node: Node): NodeResult
CoerceProc* = proc(ctx: Graphql, typeNode, node: Node): NodeResult
```
Unlike other graphql implementations, nim-graphql using a simpler approach to implement scalars.
@ -20,3 +20,76 @@ You can refer to above types definition when writing your own custom scalars.
Custom scalars main purpose is validating the user param input and validating scalar response object returned by resolver.
Custom scalars can accepts and returns whatever response object needeed by the service, but the serialization is done by execution engine.
For this reason, always keep in mind that final [response object](resolver.md#response-object) should contains only limited set of `Node` types.
```Nim
proc scalarMyScalar(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsafe, nosideEffect.} =
if node.kind == nkString:
ok(node)
else:
err("expect string, but got '$1'" % [$node.kind])
proc scalarLong(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsafe, nosideEffect.} =
## Long is a 64 bit unsigned integer.
## TODO: validate max-int 64 bit
if node.kind == nkInt:
# convert it into nkString node
ok(Node(kind: nkString, stringVal: node.intVal, pos: node.pos))
else:
err("expect int, but got '$1'" % [$node.kind])
proc initMyApi(ctx: GraphqlRef) =
ctx.customScalar("myScalar", scalarMyScalar)
ctx.customScalar("Long", scalarLong)
```
### Variable coercion
Variable coercion will use scalar proc to validate/convert the value.
But sometimes the variables serialization format doesn't provide compatible type with
scalar type. Common example is when a http graphql server receive variables in json format,
there is no way to distinguish between string and enum.
Then we need a type conversion from json string to enum node using custom coercion.
```graphql
enum Fruits {
Banana
Apple
Orange
}
enum Vehicles {
Car
Motorcycle
Bus
Truck
}
scalar UUID
```
```Nim
proc coerceEnum(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsafe, nosideEffect.} =
if node.kind == nkString:
ok(Node(kind: nkEnum, name: ctx.createName(node.stringVal), pos: node.pos))
else:
err("cannot coerce '$1' to $2" % [$node.kind, $typeNode])
proc coerceUUID(ctx: GraphqlRef, typeNode, node: Node): NodeResult {.cdecl, gcsafe, nosideEffect.} =
if node.kind == nkString:
ok(node)
elif node.kind == nkInt:
ok(Node(kind: nkString, stringVal: node.intVal, pos: node.pos))
else:
err("cannot coerce '$1' to $2" % [$node.kind, $typeNode])
proc initMyApi(ctx: GraphqlRef) =
ctx.customCoercion("Fruits", coerceEnum)
ctx.customCoercion("Vehicles", coerceEnum)
ctx.customCoercion("UUID", coerceUUID)
```
Custom coercion will be executed first, then the custom scalar or builtin scalar proc will be executed.
When a custom scalar proc is not provided it will trigger error, but custom coercion is optional.
If custom coercion proc is not provided for custom scalar or enum, it will be skipped and go to the scalar
validation.
Because after coercion there is still scalar/enum validation, usually coercion proc only do conversion and
doesn't need to do complex validation.

View File

@ -17,6 +17,7 @@
- [Scalars](scalars.md)
- [Builtin scalars](scalars.md#builtin-scalars)
- [Custom scalars](scalars.md#custom-scalars)
- [Variable coercion](scalars.md#variable-coercion)
- [Directives](directives.md)
- [Builtin directives](directives.md#)