236 lines
4.8 KiB
Go
236 lines
4.8 KiB
Go
package codegen
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"text/template"
|
|
|
|
. "github.com/cortezaproject/corteza/server/pkg/y7s"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type (
|
|
// definitions are in one file
|
|
aFuncDefs struct {
|
|
Package string
|
|
Name string
|
|
Source string
|
|
Prefix string
|
|
outputDir string
|
|
|
|
// List of imports
|
|
// Used only by generated file and not pre-generated-user-file
|
|
Imports []string
|
|
|
|
Functions aFunctionSet
|
|
}
|
|
|
|
aFunctionSet []*aFuncDef
|
|
|
|
aFuncDef struct {
|
|
Name string
|
|
Kind string
|
|
Labels map[string]string
|
|
Meta *aFuncMetaDef
|
|
Params aFuncParamSet
|
|
Results aFuncResultSet
|
|
}
|
|
|
|
aFuncParamSet []*aFuncParamDef
|
|
aFuncResultSet []*aFuncResultDef
|
|
|
|
aFuncParamDef struct {
|
|
Name string
|
|
Required bool
|
|
IsArray bool `yaml:"isArray"`
|
|
Types []*aFuncParamTypeVarDef
|
|
Meta *aFuncParamMetaDef
|
|
}
|
|
|
|
aFuncParamTypeVarDef struct {
|
|
WorkflowType string `yaml:"wf"`
|
|
GoType string `yaml:"go"`
|
|
Suffix string
|
|
}
|
|
|
|
aFuncResultDef struct {
|
|
Name string
|
|
IsArray bool `yaml:"isArray"`
|
|
WorkflowType string `yaml:"wf"`
|
|
GoType string `yaml:"go"`
|
|
Meta *aFuncParamMetaDef
|
|
}
|
|
|
|
aFuncMetaDef struct {
|
|
Short string
|
|
Description string
|
|
Visual map[string]interface{}
|
|
}
|
|
|
|
aFuncParamMetaDef struct {
|
|
Label string
|
|
Description string
|
|
Visual map[string]interface{}
|
|
}
|
|
)
|
|
|
|
func procAutomationFunctions(mm ...string) (dd []*aFuncDefs, err error) {
|
|
for _, m := range mm {
|
|
f, err := os.Open(m)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s read failed: %w", m, err)
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
var (
|
|
d = &aFuncDefs{
|
|
Package: "automation",
|
|
Source: m,
|
|
Name: path.Base(m),
|
|
outputDir: path.Dir(m),
|
|
}
|
|
)
|
|
|
|
d.Name = d.Name[:len(d.Name)-13]
|
|
|
|
if err := yaml.NewDecoder(f).Decode(d); err != nil {
|
|
return nil, fmt.Errorf("could not decode %s: %w", m, err)
|
|
}
|
|
|
|
dd = append(dd, d)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (set *aFunctionSet) UnmarshalYAML(n *yaml.Node) error {
|
|
return Each(n, func(k *yaml.Node, v *yaml.Node) (err error) {
|
|
def := &aFuncDef{Name: k.Value}
|
|
|
|
if err = v.Decode(&def); err != nil {
|
|
return err
|
|
}
|
|
|
|
if def.Kind == "" {
|
|
def.Kind = "function"
|
|
}
|
|
|
|
*set = append(*set, def)
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (set *aFuncParamSet) UnmarshalYAML(n *yaml.Node) error {
|
|
return Each(n, func(k *yaml.Node, v *yaml.Node) (err error) {
|
|
def := aFuncParamDef{}
|
|
if k != nil {
|
|
def.Name = k.Value
|
|
}
|
|
|
|
*set = append(*set, &def)
|
|
return v.Decode(&def)
|
|
})
|
|
}
|
|
|
|
func (set *aFuncResultSet) UnmarshalYAML(n *yaml.Node) error {
|
|
return Each(n, func(k *yaml.Node, v *yaml.Node) (err error) {
|
|
def := aFuncResultDef{}
|
|
if k != nil {
|
|
def.Name = k.Value
|
|
}
|
|
|
|
*set = append(*set, &def)
|
|
return v.Decode(&def)
|
|
})
|
|
}
|
|
|
|
func expandAutomationFunctionTypes(ff []*aFuncDefs, tt []*exprTypesDef) {
|
|
// index of all known types
|
|
ti := make(map[string]*exprTypeDef)
|
|
|
|
for _, t := range tt {
|
|
for typ, d := range t.Types {
|
|
ti[typ] = d
|
|
}
|
|
}
|
|
|
|
for _, f := range ff {
|
|
for _, fn := range f.Functions {
|
|
for _, p := range fn.Params {
|
|
for _, t := range p.Types {
|
|
if ti[t.WorkflowType] == nil {
|
|
fmt.Printf("%s/%s(): unknown type %q used for param %q\n", f.Prefix, fn.Name, t.WorkflowType, p.Name)
|
|
continue
|
|
}
|
|
|
|
if t.GoType == "" {
|
|
t.GoType = ti[t.WorkflowType].As
|
|
if "[]TypedValue" == t.GoType {
|
|
t.GoType = "[]expr.TypedValue"
|
|
}
|
|
}
|
|
|
|
if t.Suffix == "" && len(p.Types) > 1 {
|
|
t.Suffix = t.WorkflowType
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, r := range fn.Results {
|
|
if ti[r.WorkflowType] == nil {
|
|
fmt.Printf("%s/%s(): unknown type %q used for result %q\n", f.Prefix, fn.Name, r.WorkflowType, r.Name)
|
|
continue
|
|
}
|
|
|
|
if r.GoType == "" {
|
|
r.GoType = ti[r.WorkflowType].As
|
|
if "[]TypedValue" == r.GoType {
|
|
r.GoType = "[]expr.TypedValue"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func genAutomationFunctions(tpl *template.Template, dd ...*aFuncDefs) (err error) {
|
|
var (
|
|
// Will only be generated if file does not exist previously
|
|
tplAFuncGen = tpl.Lookup("afunc.gen.go.tpl")
|
|
|
|
dst string
|
|
)
|
|
|
|
for _, d := range dd {
|
|
// Generic code, actions for every resource goes to a separated file
|
|
dst = path.Join(d.outputDir, path.Base(d.Source)[:strings.LastIndex(path.Base(d.Source), ".")]+".gen.go")
|
|
json.NewEncoder(os.Stdout).SetIndent("", " ")
|
|
err = goTemplate(dst, tplAFuncGen, d)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// genAutomationFunctionDocs look for afunc.gen.adoc.tpl and generates afunc.gen.adoc from it
|
|
func genAutomationFunctionDocs(tpl *template.Template, docsPath string, dd ...*aFuncDefs) (err error) {
|
|
var (
|
|
typeGenAdoc = tpl.Lookup("afunc.gen.adoc.tpl")
|
|
|
|
dst string
|
|
)
|
|
|
|
dst = path.Join(docsPath, "afunc.gen.adoc")
|
|
return plainTemplate(dst, typeGenAdoc, map[string]interface{}{
|
|
"Definitions": dd,
|
|
})
|
|
}
|