-
Notifications
You must be signed in to change notification settings - Fork 0
/
scalars.go
108 lines (100 loc) · 2.79 KB
/
scalars.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package gql
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"unicode/utf8"
)
// InputCoercion func
type InputCoercion func(string) (interface{}, error)
// OutputCoercion func
type OutputCoercion func(interface{}) ([]byte, error)
// Scalar ...
type Scalar struct {
Name string
Description string
InputCoercion InputCoercion
OutputCoercion OutputCoercion
}
// Unwrap ...
func (s *Scalar) Unwrap() Type {
return nil
}
// Kind ...
func (s *Scalar) Kind() TypeDefinition {
return ScalarTypeDefinition
}
// Validate validates the Type
func (s *Scalar) Validate(ctx *ValidationContext) error {
if strings.HasPrefix(s.Name, "__") {
return fmt.Errorf("invalid name (%s) for Scalar", s.Name)
}
ctx.types[s.Name] = s
return nil
}
var (
// String is a built-in type in GraphQL
String = &Scalar{
Name: "String",
Description: "This is the built-in String scalar",
InputCoercion: func(s string) (interface{}, error) {
if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
t := s[1 : len(s)-1]
if utf8.ValidString(t) {
return t, nil
}
}
return nil, fmt.Errorf("value '%s' couldn't be coerced as input for String", s)
},
OutputCoercion: func(v interface{}) ([]byte, error) {
r := reflect.ValueOf(v)
switch {
case v == nil:
return []byte("null"), nil
case r.Kind() == reflect.String:
if utf8.ValidString(r.String()) {
return json.Marshal(r.String())
}
case r.Kind() == reflect.Bool:
if r.Bool() {
return []byte("true"), nil
}
return []byte("false"), nil
case r.Kind() == reflect.Int || r.Kind() == reflect.Int16 || r.Kind() == reflect.Int32:
return []byte(fmt.Sprintf(`"%v"`, r.Int())), nil
case r.Kind() == reflect.Float32 || r.Kind() == reflect.Float64:
return []byte(fmt.Sprintf(`"%v"`, r.Float())), nil
}
return nil, fmt.Errorf("value '%v' couldn't be coerced as output for String", v)
},
}
// ID is a built-in type in GraphQL
ID = &Scalar{
Name: "ID",
Description: "This is the built-in ID scalar",
InputCoercion: func(s string) (interface{}, error) {
if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
t := s[1 : len(s)-1]
if utf8.ValidString(t) {
return t, nil
}
}
return nil, fmt.Errorf("value '%s' couldn't be coerced as input for String", s)
},
OutputCoercion: func(v interface{}) ([]byte, error) {
r := reflect.ValueOf(v)
switch {
case v == nil:
return []byte("null"), nil
case r.Kind() == reflect.String:
if utf8.ValidString(r.String()) {
return json.Marshal(r.String())
}
case r.Kind() == reflect.Int || r.Kind() == reflect.Int16 || r.Kind() == reflect.Int32:
return []byte(fmt.Sprintf(`"%v"`, r.Int())), nil
}
return nil, fmt.Errorf("value '%v' couldn't be coerced as output for String", v)
},
}
)