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  }