217 lines
4.9 KiB
Go
217 lines
4.9 KiB
Go
package codegen
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"github.com/Masterminds/sprig"
|
|
"github.com/cortezaproject/corteza-server/pkg/cli"
|
|
"github.com/fsnotify/fsnotify"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
func Proc() {
|
|
var (
|
|
err error
|
|
|
|
watchChanges bool
|
|
beVerbose bool
|
|
|
|
fileList []string
|
|
watcher *fsnotify.Watcher
|
|
|
|
templatesPath = filepath.Join("pkg", "codegen", "assets", "*.tpl")
|
|
templatesSrc []string
|
|
|
|
actionSrcPath = filepath.Join("*", "service", "*_actions.yaml")
|
|
actionSrc []string
|
|
actionDefs []*actionsDef
|
|
|
|
eventSrcPath = filepath.Join("*", "service", "event", "events.yaml")
|
|
eventSrc []string
|
|
eventDefs []*eventsDef
|
|
|
|
// workaround because
|
|
// filepath.Join merges "*","*" into "**" instead of "*/*"
|
|
typeSrcPath = filepath.Join("*"+string(filepath.Separator)+"*", "types.yaml")
|
|
typeSrc []string
|
|
typeDefs []*typesDef
|
|
|
|
restSrcPath = filepath.Join("*", "rest.yaml")
|
|
restSrc []string
|
|
restDefs []*restDef
|
|
|
|
storeSrcPath = filepath.Join("store", "*.yaml")
|
|
storeSrc []string
|
|
storeDefs []*storeDef
|
|
|
|
tpls *template.Template
|
|
tplBase = template.New("").
|
|
Funcs(map[string]interface{}{
|
|
"camelCase": camelCase,
|
|
"export": export,
|
|
"unexport": unexport,
|
|
"toggleExport": toggleExport,
|
|
"toLower": strings.ToLower,
|
|
"cc2underscore": cc2underscore,
|
|
"normalizeImport": normalizeImport,
|
|
"comment": func(text string, skip1st bool) string {
|
|
ll := strings.Split(text, "\n")
|
|
s := 0
|
|
out := ""
|
|
if skip1st {
|
|
s = 1
|
|
out = ll[0] + "\n"
|
|
}
|
|
|
|
for ; s < len(ll); s++ {
|
|
out += "// " + ll[s] + "\n"
|
|
}
|
|
|
|
return out
|
|
},
|
|
}).
|
|
Funcs(sprig.TxtFuncMap())
|
|
|
|
output = func(format string, aa ...interface{}) {
|
|
if beVerbose {
|
|
fmt.Fprintf(os.Stdout, format, aa...)
|
|
}
|
|
}
|
|
|
|
outputErr = func(err error, format string, aa ...interface{}) bool {
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stdout, format, aa...)
|
|
fmt.Fprintf(os.Stdout, "%v\n", err)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
)
|
|
|
|
flag.BoolVar(&watchChanges, "w", false, "regenerate code on template or definition change")
|
|
flag.BoolVar(&beVerbose, "v", false, "output loaded definitions, templates and outputs")
|
|
flag.Parse()
|
|
|
|
defer func() {
|
|
if watcher != nil {
|
|
watcher.Close()
|
|
}
|
|
}()
|
|
|
|
for {
|
|
fileList = make([]string, 0, 100)
|
|
|
|
templatesSrc = glob(templatesPath)
|
|
output("loaded %d templates from %s\n", len(templatesSrc), templatesPath)
|
|
|
|
actionSrc = glob(actionSrcPath)
|
|
output("loaded %d action definitions from %s\n", len(actionSrc), actionSrcPath)
|
|
|
|
eventSrc = glob(eventSrcPath)
|
|
output("loaded %d event definitions from %s\n", len(eventSrc), eventSrcPath)
|
|
|
|
typeSrc = glob(typeSrcPath)
|
|
output("loaded %d type definitions from %s\n", len(typeSrc), typeSrcPath)
|
|
|
|
restSrc = glob(restSrcPath)
|
|
output("loaded %d rest definitions from %s\n", len(restSrc), restSrcPath)
|
|
|
|
storeSrc = glob(storeSrcPath)
|
|
output("loaded %d store definitions from %s\n", len(storeSrc), storeSrcPath)
|
|
|
|
if watchChanges {
|
|
if watcher != nil {
|
|
watcher.Close()
|
|
}
|
|
|
|
watcher, err = fsnotify.NewWatcher()
|
|
cli.HandleError(err)
|
|
|
|
fileList = append(fileList, templatesSrc...)
|
|
fileList = append(fileList, actionSrc...)
|
|
fileList = append(fileList, eventSrc...)
|
|
fileList = append(fileList, typeSrc...)
|
|
fileList = append(fileList, restSrc...)
|
|
fileList = append(fileList, storeSrc...)
|
|
|
|
for _, d := range fileList {
|
|
cli.HandleError(watcher.Add(d))
|
|
}
|
|
}
|
|
|
|
func() {
|
|
tpls, err = tplBase.ParseFiles(templatesSrc...)
|
|
if outputErr(err, "could not parse templates:\n") {
|
|
return
|
|
}
|
|
|
|
if actionDefs, err = procActions(actionSrc...); err == nil {
|
|
err = genActions(tpls, actionDefs...)
|
|
}
|
|
|
|
if outputErr(err, "failed to process actions:\n") {
|
|
return
|
|
}
|
|
|
|
if eventDefs, err = procEvents(eventSrc...); err == nil {
|
|
err = genEvents(tpls, eventDefs...)
|
|
}
|
|
|
|
if outputErr(err, "failed to process events:\n") {
|
|
return
|
|
}
|
|
|
|
if typeDefs, err = procTypes(typeSrc...); err == nil {
|
|
err = genTypes(tpls, typeDefs...)
|
|
}
|
|
|
|
if outputErr(err, "failed to process types:\n") {
|
|
return
|
|
}
|
|
|
|
if restDefs, err = procRest(restSrc...); err == nil {
|
|
err = genRest(tpls, restDefs...)
|
|
}
|
|
|
|
if outputErr(err, "failed to process rest:\n") {
|
|
return
|
|
}
|
|
|
|
if storeDefs, err = procStore(storeSrc...); err == nil {
|
|
err = genStore(tpls, storeDefs...)
|
|
}
|
|
|
|
if outputErr(err, "failed to process store:\n") {
|
|
return
|
|
}
|
|
|
|
}()
|
|
|
|
if !watchChanges {
|
|
break
|
|
}
|
|
|
|
// @todo fix this (without causing too many "too-many-files" issues :)
|
|
output("waiting for changes (if you add a new file, restart codegen manually)\n")
|
|
|
|
select {
|
|
case <-watcher.Events:
|
|
case err = <-watcher.Errors:
|
|
cli.HandleError(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func glob(path string) []string {
|
|
src, err := filepath.Glob(path)
|
|
if err != nil {
|
|
cli.HandleError(fmt.Errorf("failed to glob %q: %w", path, err))
|
|
}
|
|
|
|
return src
|
|
}
|