diff --git a/controller/controller.cli.go b/controller/controller.cli.go new file mode 100644 index 00000000..722848f3 --- /dev/null +++ b/controller/controller.cli.go @@ -0,0 +1,111 @@ +//go:build cli + +// Package controller coordinates all the other +// components in the `Lama2` project. The high +// level overview of command execution is easily +// understood from this package +package contoller + +import ( + "os" + + "github.com/HexmosTech/gabs/v2" + "github.com/HexmosTech/httpie-go" + "github.com/HexmosTech/lama2/cmdexec" + "github.com/HexmosTech/lama2/cmdgen" + "github.com/HexmosTech/lama2/codegen" + "github.com/HexmosTech/lama2/lama2cmd" + outputmanager "github.com/HexmosTech/lama2/outputManager" + "github.com/HexmosTech/lama2/parser" + "github.com/HexmosTech/lama2/preprocess" + "github.com/HexmosTech/lama2/prettify" + "github.com/HexmosTech/lama2/utils" + "github.com/dop251/goja" + "github.com/rs/zerolog/log" +) + + +func ExecuteProcessorBlock(block *gabs.Container, vm *goja.Runtime) { + b := block.S("value").Data().(*gabs.Container) + log.Debug().Str("Processor block incoming block", block.String()).Msg("") + script := b.Data().(string) + cmdexec.RunVMCode(script, vm) +} + +func ExecuteRequestorBlock(block *gabs.Container, vm *goja.Runtime, opts *lama2cmd.Opts, dir string) httpie.ExResponse { + preprocess.ProcessVarsInBlock(block, vm) + // TODO - replace stuff in headers, and varjson and json as well + cmd, stdinBody := cmdgen.ConstructCommand(block, opts) + log.Debug().Str("Stdin Body to be passed into httpie", stdinBody).Msg("") + resp, e1 := cmdexec.ExecCommand(cmd, stdinBody, dir) + log.Debug().Str("Response from ExecCommand", resp.Body).Msg("") + if e1 == nil { + chainCode := cmdexec.GenerateChainCode(resp.Body) + cmdexec.RunVMCode(chainCode, vm) + } else { + log.Fatal().Str("Error from ExecCommand", e1.Error()) + os.Exit(1) + } + return resp +} + +func HandleParsedFile(parsedAPI *gabs.Container, o *lama2cmd.Opts, dir string) { + parsedAPIblocks := GetParsedAPIBlocks(parsedAPI) + vm := cmdexec.GetJSVm() + var resp httpie.ExResponse + for i, block := range parsedAPIblocks { + log.Debug().Int("Block num", i).Msg("") + log.Debug().Str("Block getting processed", block.String()).Msg("") + blockType := block.S("type").Data().(string) + if blockType == "processor" { + ExecuteProcessorBlock(block, vm) + } else if blockType == "Lama2File" { + resp = ExecuteRequestorBlock(block, vm, o, dir) + } + } + if o.Output != "" { + outputmanager.WriteJSONOutput(resp, o.Output) + } +} + +// Process initiates the following tasks in the given order: +// 1. Parse command line arguments +// 2. Read API file contents +// 3. Expand environment variables in API file +// 4. Parse the API contents +// 5. Generate API request command +// 6. Execute command & retrieve results +// 7. Optionally, post-process and write results to a JSON file +func Process(version string) { + o := lama2cmd.GetAndValidateCmd(os.Args) + lama2cmd.ArgParsing(o, version) + + apiContent := preprocess.GetLamaFileAsString(o.Positional.LamaAPIFile) + _, dir, _ := utils.GetFilePathComponents(o.Positional.LamaAPIFile) + oldDir, _ := os.Getwd() + utils.ChangeWorkingDir(dir) + + preprocess.LoadEnvironments(dir) + utils.ChangeWorkingDir(oldDir) + p := parser.NewLama2Parser() + parsedAPI, e := p.Parse(apiContent) + if o.Convert != "" { + codegen.GenerateTargetCode(o.Convert, parsedAPI) + return + } + + if o.Prettify { + prettify.Prettify(parsedAPI, p.Context, p.MarkRange, apiContent, o.Positional.LamaAPIFile) + return + } + + if e != nil { + log.Fatal(). + Str("Type", "Controller"). + Str("LamaFile", o.Positional.LamaAPIFile). + Str("Error", e.Error()). + Msg("Parse Error") + } + log.Debug().Str("Parsed API", parsedAPI.String()).Msg("") + HandleParsedFile(parsedAPI, o, dir) +} diff --git a/controller/controller.go b/controller/controller.go index b6cee9dd..c3727343 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -1,5 +1,3 @@ -//go:build cli - // Package controller coordinates all the other // components in the `Lama2` project. The high // level overview of command execution is easily @@ -7,108 +5,10 @@ package contoller import ( - "os" - "github.com/HexmosTech/gabs/v2" - "github.com/HexmosTech/httpie-go" - "github.com/HexmosTech/lama2/cmdexec" - "github.com/HexmosTech/lama2/cmdgen" - "github.com/HexmosTech/lama2/codegen" - "github.com/HexmosTech/lama2/lama2cmd" - outputmanager "github.com/HexmosTech/lama2/outputManager" - "github.com/HexmosTech/lama2/parser" - "github.com/HexmosTech/lama2/preprocess" - "github.com/HexmosTech/lama2/prettify" - "github.com/HexmosTech/lama2/utils" - "github.com/dop251/goja" - "github.com/rs/zerolog/log" ) func GetParsedAPIBlocks(parsedAPI *gabs.Container) []*gabs.Container { return parsedAPI.S("value").Data().(*gabs.Container).Children() } -func ExecuteProcessorBlock(block *gabs.Container, vm *goja.Runtime) { - b := block.S("value").Data().(*gabs.Container) - log.Debug().Str("Processor block incoming block", block.String()).Msg("") - script := b.Data().(string) - cmdexec.RunVMCode(script, vm) -} - -func ExecuteRequestorBlock(block *gabs.Container, vm *goja.Runtime, opts *lama2cmd.Opts, dir string) httpie.ExResponse { - preprocess.ProcessVarsInBlock(block, vm) - // TODO - replace stuff in headers, and varjson and json as well - cmd, stdinBody := cmdgen.ConstructCommand(block, opts) - log.Debug().Str("Stdin Body to be passed into httpie", stdinBody).Msg("") - resp, e1 := cmdexec.ExecCommand(cmd, stdinBody, dir) - log.Debug().Str("Response from ExecCommand", resp.Body).Msg("") - if e1 == nil { - chainCode := cmdexec.GenerateChainCode(resp.Body) - cmdexec.RunVMCode(chainCode, vm) - } else { - log.Fatal().Str("Error from ExecCommand", e1.Error()) - os.Exit(1) - } - return resp -} - -func HandleParsedFile(parsedAPI *gabs.Container, o *lama2cmd.Opts, dir string) { - parsedAPIblocks := GetParsedAPIBlocks(parsedAPI) - vm := cmdexec.GetJSVm() - var resp httpie.ExResponse - for i, block := range parsedAPIblocks { - log.Debug().Int("Block num", i).Msg("") - log.Debug().Str("Block getting processed", block.String()).Msg("") - blockType := block.S("type").Data().(string) - if blockType == "processor" { - ExecuteProcessorBlock(block, vm) - } else if blockType == "Lama2File" { - resp = ExecuteRequestorBlock(block, vm, o, dir) - } - } - if o.Output != "" { - outputmanager.WriteJSONOutput(resp, o.Output) - } -} - -// Process initiates the following tasks in the given order: -// 1. Parse command line arguments -// 2. Read API file contents -// 3. Expand environment variables in API file -// 4. Parse the API contents -// 5. Generate API request command -// 6. Execute command & retrieve results -// 7. Optionally, post-process and write results to a JSON file -func Process(version string) { - o := lama2cmd.GetAndValidateCmd(os.Args) - lama2cmd.ArgParsing(o, version) - - apiContent := preprocess.GetLamaFileAsString(o.Positional.LamaAPIFile) - _, dir, _ := utils.GetFilePathComponents(o.Positional.LamaAPIFile) - oldDir, _ := os.Getwd() - utils.ChangeWorkingDir(dir) - - preprocess.LoadEnvironments(dir) - utils.ChangeWorkingDir(oldDir) - p := parser.NewLama2Parser() - parsedAPI, e := p.Parse(apiContent) - if o.Convert != "" { - codegen.GenerateTargetCode(o.Convert, parsedAPI) - return - } - - if o.Prettify { - prettify.Prettify(parsedAPI, p.Context, p.MarkRange, apiContent, o.Positional.LamaAPIFile) - return - } - - if e != nil { - log.Fatal(). - Str("Type", "Controller"). - Str("LamaFile", o.Positional.LamaAPIFile). - Str("Error", e.Error()). - Msg("Parse Error") - } - log.Debug().Str("Parsed API", parsedAPI.String()).Msg("") - HandleParsedFile(parsedAPI, o, dir) -} diff --git a/controller/controller.wasm.go b/controller/controller.wasm.go index 44a8ef92..b5a037f0 100644 --- a/controller/controller.wasm.go +++ b/controller/controller.wasm.go @@ -18,10 +18,6 @@ import ( "syscall/js" ) -func GetParsedAPIBlocks(parsedAPI *gabs.Container) []*gabs.Container { - return parsedAPI.S("value").Data().(*gabs.Container).Children() -} - func ExecuteProcessorBlock(block *gabs.Container) { b := block.S("value").Data().(*gabs.Container) script := b.Data().(string) diff --git a/lama2cmd/lama2cmd.go b/lama2cmd/lama2cmd.go index e6b041b9..ac62db0b 100644 --- a/lama2cmd/lama2cmd.go +++ b/lama2cmd/lama2cmd.go @@ -1,4 +1,3 @@ -//go:build cli // Package `lama2cmd` provides CLI argument parsing facilities. // It hosts the `Opts` structure to record user intentions diff --git a/lama2cmd/lama2cmd.wasm.go b/lama2cmd/lama2cmd.wasm.go deleted file mode 100644 index 88e1a23b..00000000 --- a/lama2cmd/lama2cmd.wasm.go +++ /dev/null @@ -1,89 +0,0 @@ -//go:build wasm - -package lama2cmd - -import ( - "fmt" - "os" - - "github.com/HexmosTech/lama2/importer" - "github.com/HexmosTech/lama2/l2lsp" - "github.com/HexmosTech/lama2/utils" - "github.com/jessevdk/go-flags" -) - -// The Opts structure stores user preferences, and is used throughout -// the module to make various decisions. -type Opts struct { - Output string `short:"o" long:"output" description:"Path to output JSON file to store logs, headers and result"` - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - Prettify bool `short:"b" long:"prettify" description:"Prettify specified .l2 file"` - Nocolor bool `short:"n" long:"nocolor" description:"Disable color in httpie output"` - Update bool `short:"u" long:"update" description:"Update l2 binary to the latest released version (Linux/MacOS only)"` - PostmanFile string `short:"p" long:"postmanfile" description:"JSON export from Postman (Settings -> Data -> Export Data)"` - LamaDir string `short:"l" long:"lama2dir" description:"Output directory to put .l2 files after conversion from Postman format"` - Help bool `short:"h" long:"help" group:"AddHelp" description:"Usage help for Lama2"` - Lsp bool `short:"z" long:"lsp" description:"Start the lsp server"` - Version bool `long:"version" description:"Print Lama2 binary version"` - - Positional struct { - LamaAPIFile string - } `positional-args:"yes"` -} - -func getParsedInput(argList []string) (Opts, []string) { - argList = argList[1:] // remove command name - o := Opts{} - - if len(argList) == 0 { - argList = append(argList, "-h") - } - args, err := flags.ParseArgs(&o, argList) - if err != nil { - e, _ := err.(*flags.Error) - if e.Type == flags.ErrHelp { - os.Exit(0) - } - } - - return o, args -} - -func ArgParsing(o *Opts, version string) { - if o.Version { - fmt.Println(version) - os.Exit(0) - } - if o.Update { - utils.UpdateSelf() - os.Exit(0) - } - if o.Lsp { - l2lsp.StartLspServer() - // Incoming requests to the LSP will be handled by l2lsp.Process() - } - if len(o.PostmanFile) > 0 { - if len(o.LamaDir) > 0 { - importer.PostmanImporter(o.PostmanFile, o.LamaDir) - os.Exit(0) - } - os.Exit(1) - } - if len(o.LamaDir) > 0 { - if len(o.PostmanFile) > 0 { - importer.PostmanImporter(o.PostmanFile, o.LamaDir) - os.Exit(0) - } - os.Exit(1) - } -} - -// GetAndValidateCmd takes in the user's CLI input, and checks -// for validity. If not OK, displays a help message in stdout. -// Otherwise, fills the Opts structure and returns it -// Moreover, based on user input, the outputManager gets configured -// (whether user prefers trace/debug/info level) -func GetAndValidateCmd(ipArgs []string) *Opts { - o, _ := getParsedInput(ipArgs) - return &o -} diff --git a/outputManager/output_manager.go b/outputManager/output_manager.go index 16629617..b6ecbb8b 100644 --- a/outputManager/output_manager.go +++ b/outputManager/output_manager.go @@ -1,4 +1,4 @@ -//go:build cli + // Package `outputmanager` provides facilities for controlling // the logging library as well as capabilities to post-process diff --git a/outputManager/output_manager.wasm.go b/outputManager/output_manager.wasm.go deleted file mode 100644 index 8cee3e72..00000000 --- a/outputManager/output_manager.wasm.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build wasm - -package outputmanager - -import ( - "bytes" - "os" - - "github.com/HexmosTech/gabs/v2" - "github.com/HexmosTech/httpie-go" -) - -var LogBuff bytes.Buffer - -func wrapError(requestError string) *gabs.Container { - temp := gabs.New() - temp.Set(requestError, "errors") - return temp -} - -func ResponseToJSON(resp httpie.ExResponse) (*gabs.Container, error) { - body := string(resp.Body) - - var headerMapStr string - for k, v := range resp.Headers { - headerMapStr += k + ": " + v + "\n" - } - - temp := gabs.New() - temp.Set(headerMapStr, "headers") - temp.Set(body, "body") - temp.Set(LogBuff.String(), "logs") - - return temp, nil -} - -func WriteJSONOutput(resp httpie.ExResponse, targetPath string) { - temp, _ := ResponseToJSON(resp) - err := os.WriteFile(targetPath, []byte(temp.String()), 0o644) - if err != nil { - } -}