github.com/vetcher/gqlgen@v0.6.0/codegen/templates/templates.go (about) 1 //go:generate go run ./inliner/inliner.go 2 3 package templates 4 5 import ( 6 "bytes" 7 "fmt" 8 "io/ioutil" 9 "log" 10 "os" 11 "path/filepath" 12 "sort" 13 "strconv" 14 "strings" 15 "text/template" 16 "unicode" 17 18 "github.com/99designs/gqlgen/internal/imports" 19 "github.com/pkg/errors" 20 ) 21 22 func Run(name string, tpldata interface{}) (*bytes.Buffer, error) { 23 t := template.New("").Funcs(template.FuncMap{ 24 "ucFirst": ucFirst, 25 "lcFirst": lcFirst, 26 "quote": strconv.Quote, 27 "rawQuote": rawQuote, 28 "toCamel": ToCamel, 29 "dump": dump, 30 "prefixLines": prefixLines, 31 }) 32 33 for filename, data := range data { 34 _, err := t.New(filename).Parse(data) 35 if err != nil { 36 panic(err) 37 } 38 } 39 40 buf := &bytes.Buffer{} 41 err := t.Lookup(name).Execute(buf, tpldata) 42 if err != nil { 43 return nil, err 44 } 45 46 return buf, nil 47 } 48 49 func ucFirst(s string) string { 50 if s == "" { 51 return "" 52 } 53 r := []rune(s) 54 r[0] = unicode.ToUpper(r[0]) 55 return string(r) 56 } 57 58 func lcFirst(s string) string { 59 if s == "" { 60 return "" 61 } 62 63 r := []rune(s) 64 r[0] = unicode.ToLower(r[0]) 65 return string(r) 66 } 67 68 func isDelimiter(c rune) bool { 69 return c == '-' || c == '_' || unicode.IsSpace(c) 70 } 71 72 func ToCamel(s string) string { 73 buffer := make([]rune, 0, len(s)) 74 upper := true 75 lastWasUpper := false 76 77 for _, c := range s { 78 if isDelimiter(c) { 79 upper = true 80 continue 81 } 82 if !lastWasUpper && unicode.IsUpper(c) { 83 upper = true 84 } 85 86 if upper { 87 buffer = append(buffer, unicode.ToUpper(c)) 88 } else { 89 buffer = append(buffer, unicode.ToLower(c)) 90 } 91 upper = false 92 lastWasUpper = unicode.IsUpper(c) 93 } 94 95 return string(buffer) 96 } 97 98 func rawQuote(s string) string { 99 return "`" + strings.Replace(s, "`", "`+\"`\"+`", -1) + "`" 100 } 101 102 func dump(val interface{}) string { 103 switch val := val.(type) { 104 case int: 105 return strconv.Itoa(val) 106 case int64: 107 return fmt.Sprintf("%d", val) 108 case float64: 109 return fmt.Sprintf("%f", val) 110 case string: 111 return strconv.Quote(val) 112 case bool: 113 return strconv.FormatBool(val) 114 case nil: 115 return "nil" 116 case []interface{}: 117 var parts []string 118 for _, part := range val { 119 parts = append(parts, dump(part)) 120 } 121 return "[]interface{}{" + strings.Join(parts, ",") + "}" 122 case map[string]interface{}: 123 buf := bytes.Buffer{} 124 buf.WriteString("map[string]interface{}{") 125 var keys []string 126 for key := range val { 127 keys = append(keys, key) 128 } 129 sort.Strings(keys) 130 131 for _, key := range keys { 132 data := val[key] 133 134 buf.WriteString(strconv.Quote(key)) 135 buf.WriteString(":") 136 buf.WriteString(dump(data)) 137 buf.WriteString(",") 138 } 139 buf.WriteString("}") 140 return buf.String() 141 default: 142 panic(fmt.Errorf("unsupported type %T", val)) 143 } 144 } 145 146 func prefixLines(prefix, s string) string { 147 return prefix + strings.Replace(s, "\n", "\n"+prefix, -1) 148 } 149 150 func RenderToFile(tpl string, filename string, data interface{}) error { 151 var buf *bytes.Buffer 152 buf, err := Run(tpl, data) 153 if err != nil { 154 return errors.Wrap(err, filename+" generation failed") 155 } 156 157 if err := write(filename, buf.Bytes()); err != nil { 158 return err 159 } 160 161 log.Println(filename) 162 163 return nil 164 } 165 166 func write(filename string, b []byte) error { 167 err := os.MkdirAll(filepath.Dir(filename), 0755) 168 if err != nil { 169 return errors.Wrap(err, "failed to create directory") 170 } 171 172 formatted, err := imports.Prune(filename, b) 173 if err != nil { 174 fmt.Fprintf(os.Stderr, "gofmt failed on %s: %s\n", filepath.Base(filename), err.Error()) 175 formatted = b 176 } 177 178 err = ioutil.WriteFile(filename, formatted, 0644) 179 if err != nil { 180 return errors.Wrapf(err, "failed to write %s", filename) 181 } 182 183 return nil 184 }