yao/pipe/node.go
2024-02-13 20:54:25 +08:00

276 lines
4.8 KiB
Go

package pipe
import (
"fmt"
"strings"
"github.com/yaoapp/kun/log"
"github.com/yaoapp/kun/utils"
"github.com/yaoapp/yao/pipe/ui/cli"
)
// ExecProcess Execute the process
func (node Node) ExecProcess(ctx *Context, args []any) error {
var err error
name := node.Namespace()
ctx.in[name] = args
if node.Input != nil {
ctx.in[name], err = ctx.replaceInput(node.Input)
if err != nil {
return err
}
}
ctx.input[name] = ctx.in[name]
res := true
ctx.out[name] = res
ctx.output[name] = res
if node.Output != nil {
ctx.output[name], err = ctx.replace(node.Output)
if err != nil {
return err
}
}
next, err := ctx.Next()
if err != nil {
if IsEOF(err) {
return nil
}
return err
}
// Execute the next node
_, err = ctx.exec(next, ctx.output[name])
if err != nil {
return err
}
return nil
}
// ExecRequest Execute the request
func (node Node) ExecRequest(ctx *Context, args []any) error {
return nil
}
// ExecAI Execute the AI
func (node Node) ExecAI(ctx *Context, args []any) error {
var err error
name := node.Namespace()
ctx.in[name] = args
if node.Input != nil {
ctx.in[name], err = ctx.replaceInput(node.Input)
if err != nil {
return err
}
}
ctx.input[name] = ctx.in[name]
res := map[string]any{"args": args, "Chinese": "你好", "Arabic": "مرحبا"}
ctx.out[name] = res
ctx.output[name] = res
if node.Output != nil {
ctx.output[name], err = ctx.replace(node.Output)
if err != nil {
return err
}
}
next, err := ctx.Next()
if err != nil {
if IsEOF(err) {
return nil
}
return err
}
// Execute the next node
_, err = ctx.exec(next, ctx.output[name])
if err != nil {
return err
}
return nil
}
// ExecSwitch Execute the switch
func (node Node) ExecSwitch(ctx *Context, args []any) error {
var err error
name := node.Namespace()
ctx.in[name] = args
if node.Input != nil {
ctx.in[name], err = ctx.replaceInput(node.Input)
if err != nil {
return err
}
}
ctx.input[name] = ctx.in[name]
data, err := ctx.data()
if err != nil {
return err
}
section, _ := node.Case["default"]
for stmt := range node.Case {
if stmt == "default" {
continue
}
v, err := data.Exec(stmt)
if err != nil {
log.Warn("pipe: %s %s", ctx.Name, err)
continue
}
// If the result is true, then break the loop
if match, ok := v.(bool); ok && match {
section = node.Case[stmt]
break
}
}
// Execute the next node
if section == nil {
return fmt.Errorf("pipe: %s %s", ctx.Name, "node case not matched")
}
// Execute The Pipe
subCtx := section.Create().
With(ctx.context).
WithGlobal(ctx.global).
WithSid(ctx.sid)
// Copy the input and output
for k, v := range ctx.in {
subCtx.in[k] = v
}
for k, v := range ctx.input {
subCtx.input[k] = v
}
for k, v := range ctx.out {
subCtx.out[k] = v
}
for k, v := range ctx.output {
subCtx.output[k] = v
}
_, err = subCtx.Exec(ctx.in[name])
if err != nil {
return err
}
// Merge the output
for k, v := range subCtx.out {
ctx.out[k] = v
}
for k, v := range subCtx.output {
ctx.output[k] = v
}
utils.Dump(name, ctx.output)
return nil
}
// Render Execute the user input
func (node Node) Render(ctx *Context, args []any) error {
switch node.UI {
case "cli":
return node.renderCli(ctx, args)
case "web":
default:
return fmt.Errorf("pipe: %s %s", ctx.Name, "node ui not supported")
}
return nil
}
// Namespace the node namespace
func (node Node) Namespace() string {
name := node.Name
if node.namespace != "" {
name = fmt.Sprintf("%s.%s", node.namespace, name)
}
return name
}
func (node Node) renderCli(ctx *Context, args []any) error {
var err error
name := node.Namespace()
ctx.in[name] = args
if node.Input != nil {
ctx.in[name], err = ctx.replaceInput(node.Input)
if err != nil {
return err
}
}
ctx.input[name] = ctx.in[name]
// Set option
label, err := ctx.replaceString(node.Label)
if err != nil {
return err
}
option := &cli.Option{Label: label}
if node.AutoFill != nil {
value := fmt.Sprintf("%v", node.AutoFill.Value)
value, err = ctx.replaceString(value)
if value != "" {
if err != nil {
fmt.Println("cmd", err)
return err
}
if node.AutoFill.Action == "exit" {
value = fmt.Sprintf("%s\nexit()\n", value)
}
option.Reader = strings.NewReader(value)
}
}
userDataLines, err := cli.New(option).Render(args)
if err != nil {
return err
}
ctx.out[name] = userDataLines
ctx.output[name] = userDataLines
if node.Output != nil {
ctx.output[name], err = ctx.replace(node.Output)
if err != nil {
return err
}
}
// Execute the next node
next, err := ctx.Next()
if err != nil {
if IsEOF(err) {
return nil
}
return err
}
// Execute the next node
_, err = ctx.exec(next, ctx.output[name])
if err != nil {
return err
}
// Next node
return nil
}