Added jsenv support to workflows
This commit is contained in:
+175
@@ -0,0 +1,175 @@
|
||||
package automation
|
||||
|
||||
// This file is auto-generated.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
//
|
||||
// Definitions file that controls how this file is generated:
|
||||
// automation/automation/jsenv_handler.yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
atypes "github.com/cortezaproject/corteza-server/automation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/wfexec"
|
||||
"io"
|
||||
)
|
||||
|
||||
var _ wfexec.ExecResponse
|
||||
|
||||
type (
|
||||
jsenvHandlerRegistry interface {
|
||||
AddFunctions(ff ...*atypes.Function)
|
||||
Type(ref string) expr.Type
|
||||
}
|
||||
)
|
||||
|
||||
func (h jsenvHandler) register() {
|
||||
h.reg.AddFunctions(
|
||||
h.Execute(),
|
||||
)
|
||||
}
|
||||
|
||||
type (
|
||||
jsenvExecuteArgs struct {
|
||||
hasScope bool
|
||||
Scope interface{}
|
||||
scopeAny interface{}
|
||||
scopeString string
|
||||
scopeStream io.Reader
|
||||
|
||||
hasSource bool
|
||||
Source string
|
||||
}
|
||||
|
||||
jsenvExecuteResults struct {
|
||||
ResultString string
|
||||
ResultInt int64
|
||||
ResultAny interface{}
|
||||
}
|
||||
)
|
||||
|
||||
func (a jsenvExecuteArgs) GetScope() (bool, interface{}, string, io.Reader) {
|
||||
return a.hasScope, a.scopeAny, a.scopeString, a.scopeStream
|
||||
}
|
||||
|
||||
// Execute function Process arbitrary data in jsenv
|
||||
//
|
||||
// expects implementation of execute function:
|
||||
// func (h jsenvHandler) execute(ctx context.Context, args *jsenvExecuteArgs) (results *jsenvExecuteResults, err error) {
|
||||
// return
|
||||
// }
|
||||
func (h jsenvHandler) Execute() *atypes.Function {
|
||||
return &atypes.Function{
|
||||
Ref: "jsenvExecute",
|
||||
Kind: "function",
|
||||
Labels: map[string]string(nil),
|
||||
Meta: &atypes.FunctionMeta{
|
||||
Short: "Process arbitrary data in jsenv",
|
||||
},
|
||||
|
||||
Parameters: []*atypes.Param{
|
||||
{
|
||||
Name: "scope",
|
||||
Types: []string{"Any", "String", "Reader"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "source",
|
||||
Types: []string{"String"}, Required: true,
|
||||
},
|
||||
},
|
||||
|
||||
Results: []*atypes.Param{
|
||||
|
||||
{
|
||||
Name: "resultString",
|
||||
Types: []string{"String"},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "resultInt",
|
||||
Types: []string{"Integer"},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "resultAny",
|
||||
Types: []string{"Any"},
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
|
||||
var (
|
||||
args = &jsenvExecuteArgs{
|
||||
hasScope: in.Has("scope"),
|
||||
hasSource: in.Has("source"),
|
||||
}
|
||||
)
|
||||
|
||||
if err = in.Decode(args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Converting Scope argument
|
||||
if args.hasScope {
|
||||
aux := expr.Must(expr.Select(in, "scope"))
|
||||
switch aux.Type() {
|
||||
case h.reg.Type("Any").Type():
|
||||
args.scopeAny = aux.Get().(interface{})
|
||||
case h.reg.Type("String").Type():
|
||||
args.scopeString = aux.Get().(string)
|
||||
case h.reg.Type("Reader").Type():
|
||||
args.scopeStream = aux.Get().(io.Reader)
|
||||
}
|
||||
}
|
||||
|
||||
var results *jsenvExecuteResults
|
||||
if results, err = h.execute(ctx, args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out = &expr.Vars{}
|
||||
|
||||
{
|
||||
// converting results.ResultString (string) to String
|
||||
var (
|
||||
tval expr.TypedValue
|
||||
)
|
||||
|
||||
if tval, err = h.reg.Type("String").Cast(results.ResultString); err != nil {
|
||||
return
|
||||
} else if err = expr.Assign(out, "resultString", tval); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// converting results.ResultInt (int64) to Integer
|
||||
var (
|
||||
tval expr.TypedValue
|
||||
)
|
||||
|
||||
if tval, err = h.reg.Type("Integer").Cast(results.ResultInt); err != nil {
|
||||
return
|
||||
} else if err = expr.Assign(out, "resultInt", tval); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// converting results.ResultAny (interface{}) to Any
|
||||
var (
|
||||
tval expr.TypedValue
|
||||
)
|
||||
|
||||
if tval, err = h.reg.Type("Any").Cast(results.ResultAny); err != nil {
|
||||
return
|
||||
} else if err = expr.Assign(out, "resultAny", tval); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package automation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/jsenv"
|
||||
)
|
||||
|
||||
type (
|
||||
jsenvHandler struct {
|
||||
reg queueHandlerRegistry
|
||||
}
|
||||
)
|
||||
|
||||
func JsenvHandler(reg queueHandlerRegistry) *jsenvHandler {
|
||||
h := &jsenvHandler{
|
||||
reg: reg,
|
||||
}
|
||||
|
||||
h.register()
|
||||
return h
|
||||
}
|
||||
|
||||
func (h jsenvHandler) execute(ctx context.Context, args *jsenvExecuteArgs) (res *jsenvExecuteResults, err error) {
|
||||
res = &jsenvExecuteResults{}
|
||||
|
||||
if !args.hasSource {
|
||||
err = fmt.Errorf("could not process payload, function missing")
|
||||
return
|
||||
}
|
||||
|
||||
if !args.hasScope {
|
||||
err = fmt.Errorf("could not process payload, scope missing")
|
||||
return
|
||||
}
|
||||
|
||||
// call jsenv, feed it function and expect a result
|
||||
tr := jsenv.NewTransformer(jsenv.LoaderJS, jsenv.TargetNoop)
|
||||
vm := jsenv.New(tr)
|
||||
|
||||
fn, err := vm.RegisterFunction(args.Source)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not register jsenv function: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
out, err := fn.Exec(vm.New(args.scopeString))
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not exec jsenv function: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch vv := out.(type) {
|
||||
|
||||
// this one should go out once the ResultAny
|
||||
// is mainly used
|
||||
case uint64, int64:
|
||||
res.ResultInt = int64(vv.(uint64))
|
||||
|
||||
// this one should go out once the ResultAny
|
||||
// is mainly used
|
||||
case string:
|
||||
res.ResultString = string(vv)
|
||||
|
||||
default:
|
||||
res.ResultAny = vv
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
imports:
|
||||
- io
|
||||
|
||||
functions:
|
||||
execute:
|
||||
meta:
|
||||
short: Process arbitrary data in jsenv
|
||||
params:
|
||||
scope:
|
||||
required: true
|
||||
types:
|
||||
- { wf: Any }
|
||||
- { wf: String, suffix: String }
|
||||
- { wf: Reader, suffix: Stream }
|
||||
source:
|
||||
required: true
|
||||
types:
|
||||
- { wf: String }
|
||||
results:
|
||||
resultString:
|
||||
wf: String
|
||||
resultInt:
|
||||
wf: Integer
|
||||
resultAny:
|
||||
wf: Any
|
||||
@@ -1,10 +1,11 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/cortezaproject/corteza-server/automation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/automation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
@@ -120,6 +120,7 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock
|
||||
automation.HttpRequestHandler(Registry())
|
||||
automation.LogHandler(Registry())
|
||||
automation.QueueHandler(Registry())
|
||||
automation.JsenvHandler(Registry())
|
||||
automation.LoopHandler(Registry(), DefaultWorkflow.parser)
|
||||
automation.CorredorHandler(Registry(), corredor.Service())
|
||||
automation.EmailHandler(Registry())
|
||||
|
||||
Reference in New Issue
Block a user