github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/engine/function/jsfuncs.go (about) 1 package funcs 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/dop251/goja" 8 "github.com/mdaxf/iac/logger" 9 "github.com/robertkrimen/otto" 10 ) 11 12 type JSFuncs struct { 13 } 14 15 // Execute executes the JavaScript function defined in the Funcs object. 16 // It sets the inputs, runs the JavaScript code, and sets the outputs. 17 // If there is an error during execution, it logs the error and returns. 18 // The execution time is also logged. 19 func (cf *JSFuncs) Execute(f *Funcs) { 20 startTime := time.Now() 21 defer func() { 22 elapsed := time.Since(startTime) 23 f.iLog.PerformanceWithDuration("engine.funcs.JSFuncs.Execute", elapsed) 24 }() 25 defer func() { 26 if err := recover(); err != nil { 27 errmsg := fmt.Sprintf("There is error to engine.funcs.JSFuncs.Execute with error: %s", err) 28 f.iLog.Error(errmsg) 29 f.CancelExecution(errmsg) 30 f.ErrorMessage = errmsg 31 return 32 } 33 }() 34 f.iLog.Debug(fmt.Sprintf("Start process %s : %s", "JSFuncs.Execute", f.Fobj.Name)) 35 36 namelist, _, inputs := f.SetInputs() 37 38 vm := goja.New() 39 40 for i := 0; i < len(namelist); i++ { 41 vm.Set(namelist[i], inputs[namelist[i]]) 42 } 43 f.iLog.Debug(fmt.Sprintf("Fucntion %s script: %s", f.Fobj.Name, f.Fobj.Content)) 44 45 value, err := vm.RunString(f.Fobj.Content) 46 if err != nil { 47 f.iLog.Error(fmt.Sprintf("Error in JSFuncs.Execute: %s", err.Error())) 48 return 49 } 50 51 result := value.Export() 52 f.iLog.Debug(fmt.Sprintf("Fucntion %s result: %s", f.Fobj.Name, result)) 53 54 outputs := make(map[string]interface{}) 55 56 for i := 0; i < len(f.Fobj.Outputs); i++ { 57 value := vm.Get(f.Fobj.Outputs[i].Name) 58 outputs[f.Fobj.Outputs[i].Name] = value.String() 59 } 60 f.iLog.Debug(fmt.Sprintf("Fucntion %s outputs: %s", f.Fobj.Name, outputs)) 61 f.SetOutputs(outputs) 62 } 63 64 // Validate validates the given Funcs object using JavaScript functions. 65 // It executes the JavaScript code stored in the Content field of the Funcs object using the goja VM. 66 // If the JavaScript code throws an error, it returns false and the error. 67 // Otherwise, it returns true and nil. 68 69 func (cf *JSFuncs) Validate(f *Funcs) (bool, error) { 70 startTime := time.Now() 71 defer func() { 72 elapsed := time.Since(startTime) 73 f.iLog.PerformanceWithDuration("engine.funcs.JSFuncs.Validate", elapsed) 74 }() 75 /* defer func() { 76 if err := recover(); err != nil { 77 f.iLog.Error(fmt.Sprintf("There is error to engine.funcs.JSFuncs.Validate with error: %s", err)) 78 f.ErrorMessage = fmt.Sprintf("There is error to engine.funcs.JSFuncs.Validate with error: %s", err) 79 return 80 } 81 }() 82 */ 83 vm := goja.New() 84 _, err := vm.RunString(f.Fobj.Content) 85 if err != nil { 86 return false, err 87 } 88 89 return true, nil 90 } 91 92 // Testfunction is a function that executes JavaScript code using the goja VM. 93 // It takes a content string, inputs interface{}, and outputs []string as parameters. 94 // The function returns a map[string]interface{} containing the values of the specified outputs, 95 // and an error if there was an error during execution. 96 // The execution time is also logged. 97 func (cf *JSFuncs) Testfunction(content string, inputs interface{}, outputs []string) (map[string]interface{}, error) { 98 iLog := logger.Log{ModuleName: logger.TranCode, User: "System", ControllerName: "JSFuncs"} 99 startTime := time.Now() 100 defer func() { 101 elapsed := time.Since(startTime) 102 iLog.PerformanceWithDuration("engine.funcs.JSFuncs.Execute", elapsed) 103 }() 104 defer func() { 105 if err := recover(); err != nil { 106 iLog.Error(fmt.Sprintf("There is error to engine.funcs.JSFuncs.Execute with error: %s", err)) 107 //ErrorMessage = fmt.Sprintf("There is error to engine.funcs.JSFuncs.Execute with error: %s", err) 108 return 109 } 110 }() 111 112 namelist := make([]string, 0) 113 valuelist := make([]interface{}, 0) 114 115 for key, value := range inputs.(map[string]interface{}) { 116 namelist = append(namelist, key) 117 valuelist = append(valuelist, value) 118 } 119 120 vm := goja.New() 121 122 for i := 0; i < len(namelist); i++ { 123 vm.Set(namelist[i], valuelist[i]) 124 } 125 126 value, err := vm.RunString(content) 127 128 if err != nil { 129 println(err.Error()) 130 return nil, err 131 } 132 133 result := value.Export() 134 functionoutputs := make(map[string]interface{}) 135 136 println(result) 137 138 for i := 0; i < len(outputs); i++ { 139 value := vm.Get(outputs[i]) 140 functionoutputs[outputs[i]] = value 141 } 142 143 return functionoutputs, nil 144 } 145 146 func (cf *JSFuncs) Execute_otto(f *Funcs) { 147 startTime := time.Now() 148 defer func() { 149 elapsed := time.Since(startTime) 150 f.iLog.PerformanceWithDuration("engine.funcs.JSFuncs.Execute", elapsed) 151 }() 152 defer func() { 153 if err := recover(); err != nil { 154 f.iLog.Error(fmt.Sprintf("There is error to engine.funcs.JSFuncs.Execute with error: %s", err)) 155 f.ErrorMessage = fmt.Sprintf("There is error to engine.funcs.JSFuncs.Execute with error: %s", err) 156 return 157 } 158 }() 159 f.iLog.Debug(fmt.Sprintf("Start process %s : %s", "JSFuncs.Execute", f.Fobj.Name)) 160 161 namelist, _, inputs := f.SetInputs() 162 163 vm := otto.New() 164 for i := 0; i < len(namelist); i++ { 165 vm.Set(namelist[i], inputs[namelist[i]]) 166 } 167 f.iLog.Debug(fmt.Sprintf("Fucntion %s script: %s", f.Fobj.Name, f.Fobj.Content)) 168 169 vm.Run(f.Fobj.Content) 170 171 outputs := make(map[string]interface{}) 172 173 for i := 0; i < len(f.Fobj.Outputs); i++ { 174 if value, err := vm.Get(f.Fobj.Outputs[i].Name); err == nil { 175 outputs[f.Fobj.Outputs[i].Name] = value.String() 176 } else { 177 f.iLog.Error(fmt.Sprintf("Error in JSFuncs.Execute: %s", err.Error())) 178 return 179 } 180 } 181 182 f.SetOutputs(outputs) 183 } 184 185 func (cf *JSFuncs) Validate_otto(f *Funcs) (bool, error) { 186 vm := otto.New() 187 _, err := vm.Compile("", f.Fobj.Content) 188 if err != nil { 189 return false, err 190 } 191 192 return true, nil 193 } 194 195 func (cf *JSFuncs) Testfunction_otto(content string, inputs interface{}, outputs []string) (map[string]interface{}, error) { 196 197 /* pass, err := cf.Validate(f) 198 199 if !pass { 200 return nil, err 201 } 202 */ 203 namelist := make([]string, 0) 204 valuelist := make([]interface{}, 0) 205 206 for key, value := range inputs.(map[string]interface{}) { 207 namelist = append(namelist, key) 208 valuelist = append(valuelist, value) 209 } 210 211 vm := otto.New() 212 for i := 0; i < len(namelist); i++ { 213 vm.Set(namelist[i], valuelist[i]) 214 } 215 216 vm.Run(content) 217 218 functionoutputs := make(map[string]interface{}) 219 220 for i := 0; i < len(outputs); i++ { 221 if value, err := vm.Get(outputs[i]); err == nil { 222 functionoutputs[outputs[i]] = value 223 } else { 224 fmt.Println(err) 225 } 226 } 227 return functionoutputs, nil 228 }