fixes scalars and variable coercion documentation
This commit is contained in:
parent
2242dc6dcc
commit
942a06c11e
|
@ -3,7 +3,7 @@
|
||||||
```Nim
|
```Nim
|
||||||
type
|
type
|
||||||
NodeResult* = Result[Node, string]
|
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.
|
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 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.
|
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.
|
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.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
- [Scalars](scalars.md)
|
- [Scalars](scalars.md)
|
||||||
- [Builtin scalars](scalars.md#builtin-scalars)
|
- [Builtin scalars](scalars.md#builtin-scalars)
|
||||||
- [Custom scalars](scalars.md#custom-scalars)
|
- [Custom scalars](scalars.md#custom-scalars)
|
||||||
|
- [Variable coercion](scalars.md#variable-coercion)
|
||||||
|
|
||||||
- [Directives](directives.md)
|
- [Directives](directives.md)
|
||||||
- [Builtin directives](directives.md#)
|
- [Builtin directives](directives.md#)
|
||||||
|
|
Loading…
Reference in New Issue