Skip to content
Closed
2 changes: 2 additions & 0 deletions cmdexec/cmdexec.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
// Once execution finishes, previous CWD is restored,
// and the command output is returned as a string
func ExecCommand(cmdSlice []string, stdinBody string, apiDir string) (httpie.ExResponse, int64, error) {
fmt.Println("WASM: Executing command")
proxyURL := os.Getenv("PROXY_URL")
proxyUserName := os.Getenv("PROXY_USERNAME")
proxyUserPassword := os.Getenv("PROXY_PASSWORD")
Expand All @@ -35,5 +36,6 @@ func ExecCommand(cmdSlice []string, stdinBody string, apiDir string) (httpie.ExR
fmt.Println("Got error while executing", err)
return httpie.ExResponse{}, 0, errors.New("Error from API executor: " + err.Error())
}
fmt.Println("WASM: Command executed successfully")
return resp, responseTime, nil
}
6 changes: 5 additions & 1 deletion cmdexec/js.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
package cmdexec

import (
"fmt"
"syscall/js"

"github.com/rs/zerolog/log"
)

// RunVMCode takes in a JS snippet as a string, executes the code in a JS VM using Web Worker
func RunVMCode(jsCode string, vm interface{}) {
fmt.Println("WASM: Running VM code")
worker := vm.(js.Value)
resultChan := make(chan js.Value)
worker.Call("postMessage", map[string]interface{}{
Expand All @@ -26,10 +28,12 @@ func RunVMCode(jsCode string, vm interface{}) {
if err != "null" {
log.Fatal().Str("Error executing JS processor block", err).Msg("")
}
fmt.Println("WASM: VM code executed successfully")
}

// GenerateChainCode takes in an HTTP response body and comes up with some JS code to define the "magic variable" result.
func GenerateChainCode(httpRespBody string) string {
fmt.Println("WASM: Generating chain code")
code := `try {
result = JSON.parse(String.raw` + "`" + httpRespBody + "`" + `)
console.log("Stored as JSON")
Expand All @@ -38,6 +42,6 @@ func GenerateChainCode(httpRespBody string) string {
console.log(e)
console.log("Stored as string")
}`
log.Debug().Str("Chain code generated", code).Msg("")
fmt.Println("WASM: Chain code generated", code)
return code
}
126 changes: 118 additions & 8 deletions cmdgen/cmdgen.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,136 @@
package cmdgen

import (
"log"
"syscall/js"

"github.com/HexmosTech/gabs/v2"
"github.com/HexmosTech/lama2/lama2cmd"
"syscall/js"
)


func ConstructCommand(parsedInput *gabs.Container, o *lama2cmd.Opts) ([]string, string) {
httpv, url, jsonObj, headers, multipartBool, formBool := ConstructCommandHelper(parsedInput)
res, stdinBody := assembleCmdString(httpv, url, jsonObj, headers, multipartBool, formBool, nil)

LaBearerAuthToken := js.Global().Get("LaBearerAuthToken").String()
authHeaderExists := false
for _, header := range res {
if len(header) >= len("Authorization:") && header[:len("Authorization:")] == "Authorization:" {
authHeaderExists = true
log.Printf("WASM: Initial command: %v", res)

manifestObj := js.Global().Get("liveapiManifest")
if manifestObj.IsUndefined() {
log.Printf("WASM: liveapiManifest is undefined, returning early")
return res, stdinBody
}
manifestData := manifestObj.String()
log.Printf("WASM: Found manifest data: %s", manifestData)

// Parse JSON
parsedJson, err := gabs.ParseJSON([]byte(manifestData))
if err != nil {
log.Printf("WASM: Error parsing JSON: %v", err)
return res, stdinBody
}

// Get project count
projects, ok := parsedJson.Path("projects").Data().([]interface{})
if !ok {
log.Printf("WASM: Failed to parse projects from manifest")
return res, stdinBody
}
log.Printf("WASM: Found %d projects in manifest", len(projects))

projectRoot := getProjectRoot()
if projectRoot == "" {
log.Printf("WASM: Project root is empty")
return res, stdinBody
}
log.Printf("WASM: Current project root: %s", projectRoot)

var selectedAuthHeader string

// Find the matching project
for _, project := range projects {
projectMap, ok := project.(map[string]interface{})
if !ok {
continue
}

if projectMap["project_root"] == projectRoot {
authData, exists := projectMap["result"].(map[string]interface{})["auth"]
if !exists {
} else {
authArray, ok := authData.([]interface{})
if !ok {
return res, stdinBody
}

// Filter the auth methods where "selected" is true
for _, authEntry := range authArray {
authMap, ok := authEntry.(map[string]interface{})
if !ok {
continue
}

selected, exists := authMap["selected"].(bool)
if exists && selected {
// Construct Authorization header based on type
authType := authMap["type"].(string)
authValue := authMap["value"].(map[string]interface{})
switch authType {
case "bearer-token":
if token, ok := authValue["token"].(string); ok {
selectedAuthHeader = "Authorization: Bearer " + token
}
case "jwt":
if jwt, ok := authValue["jwt"].(string); ok {
selectedAuthHeader = "Authorization: Bearer " + jwt
}
case "api-key":
if key, ok := authValue["key"].(string); ok {
if value, ok := authValue["value"].(string); ok {
selectedAuthHeader = key + ": " + value
}
}
case "basic-auth":
if username, ok := authValue["username"].(string); ok {
if password, ok := authValue["password"].(string); ok {
credentials := username + ":" + password
encoded := js.Global().Get("btoa").Invoke(credentials).String()
selectedAuthHeader = "Authorization: Basic " + encoded
}
}
}
break // Stop after the first selected auth method
}
}
}
break
}
}
// Add the selected authentication method to headers if not already present
if selectedAuthHeader != "" {
authHeaderExists := false
for _, header := range res {
if len(header) >= len("Authorization:") && header[:len("Authorization:")] == "Authorization:" {
authHeaderExists = true
break
}
}

if !authHeaderExists {
res = append(res, "Authorization: Bearer "+LaBearerAuthToken)
if !authHeaderExists {
res = append(res, selectedAuthHeader)
}
}

return res, stdinBody
}



func getProjectRoot() string {
// Fetch project_root from the <meta> tag in the document
meta := js.Global().Get("document").Call("querySelector", `meta[name="project_root"]`)
if meta.IsNull() {
return ""
}
return meta.Call("getAttribute", "content").String()
}
23 changes: 14 additions & 9 deletions codegen/codegen.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ var flag = 0

//go:noinline
func GenerateTargetCode(targetLangLib string, parsedAPI *gabs.Container) string {
fmt.Println("WASM: Generating target code")
convertedSnippetFinal := generateConvertedSippet(targetLangLib, parsedAPI)
fmt.Println("This is the converted snippet:", convertedSnippetFinal)
fmt.Println("WASM: This is the converted snippet:", convertedSnippetFinal)
return convertedSnippetFinal
}

Expand All @@ -35,33 +36,34 @@ func asyncTask(resultChan0 chan<- string) {

//go:noinline
func generateConvertedSippet(targetLangLib string, parsedAPI *gabs.Container) string {
fmt.Println("WASM: Generating converted snippet")
parsedAPIblocks := parsedAPI.S("value").Data().(*gabs.Container).Children()
convertedSnippetList := make([]string, 0)
blockLength := len(parsedAPIblocks)
fmt.Println("Parsed API", parsedAPIblocks)
fmt.Println("WASM: Parsed API", parsedAPIblocks)
for i, block := range parsedAPIblocks {
blockType := block.S("type").Data().(string)
fmt.Println("Block type:", blockType)
fmt.Println("WASM: Block type:", blockType)
if blockType == "processor" {
fmt.Println("Block type is processor")
fmt.Println("WASM: Block type is processor")
snippet := block.S("value").Data().(*gabs.Container).Data().(string)
log.Debug().Str("Processor block incoming block", block.String()).Msg("")
convertedSnippetList = append(convertedSnippetList, snippet)
} else if blockType == "Lama2File" {
fmt.Println("Block type is L2File")
fmt.Println("WASM: Block type is L2File")
harRequest, flag := GetRequestHARString(block, targetLangLib)
fmt.Println("HAR request:", harRequest)
fmt.Println("WASM: HAR request:", harRequest)
snippetArgs := SnippetArgs{}
lang, lib := SplitLangLib(targetLangLib)
fmt.Println("Target lang:", lang)
fmt.Println("WASM: Target lang:", lang)
snippetArgs.Language = lang
snippetArgs.Library = lib
snippetArgs.HARRequest = harRequest
snippetArgs.SnippetCore = snippetcore
fmt.Println("Snippet args:", snippetArgs)
fmt.Println("WASM: Snippet args:", snippetArgs)
httpsnippetCode := PrepareHTTPSnippetGenerator(snippetArgs)
convertedSnippet := js.Global().Call("eval", httpsnippetCode)
fmt.Println("convertedSnippet data:", convertedSnippet.String())
fmt.Println("WASM: convertedSnippet data:", convertedSnippet.String())
// convertedSnippet, err := evaluateJSCode(httpsnippetCode)
// if err != nil {
// log.Fatal().
Expand All @@ -79,6 +81,7 @@ func generateConvertedSippet(targetLangLib string, parsedAPI *gabs.Container) st
}

convertedSnippetFinal := strings.Join(convertedSnippetList, "\n")
fmt.Println("WASM: Converted snippet final:", convertedSnippetFinal)
return convertedSnippetFinal
}

Expand Down Expand Up @@ -112,6 +115,7 @@ func generateConvertedSippet(targetLangLib string, parsedAPI *gabs.Container) st

//go:noinline
func PrepareHTTPSnippetGenerator(snippetArgs SnippetArgs) string {
fmt.Println("WASM: Snippet args:", snippetArgs)
var templOutput bytes.Buffer
templStr := `{{.SnippetCore}}

Expand All @@ -121,5 +125,6 @@ func PrepareHTTPSnippetGenerator(snippetArgs SnippetArgs) string {
`
tmpl, _ := template.New("httpsnippet").Parse(templStr)
tmpl.Execute(&templOutput, snippetArgs)
fmt.Println("WASM: Templ output:")
return templOutput.String()
}
27 changes: 17 additions & 10 deletions controller/controller.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,58 +24,62 @@ import (
var worker js.Value

func HandleParsedFile(parsedAPI *gabs.Container) (httpie.ExResponse, *lama2cmd.Opts, []outputmanager.ResponseTime, []outputmanager.StatusCode, []outputmanager.ContentSize, error) {
fmt.Println("HandleParsedFile:")
fmt.Println("HandleParsedFile:", parsedAPI)
fmt.Println("WASM: HandleParsedFile:")
fmt.Println("WASM: HandleParsedFile:", parsedAPI)
return HandleParsedFileHelper(parsedAPI)
}

func ProcessWasmInput(data string) (httpie.ExResponse, *lama2cmd.Opts, []outputmanager.ResponseTime, []outputmanager.StatusCode, []outputmanager.ContentSize, error) {
fmt.Println("WASM: ProcessWasmInput")
apiContent := data
p := parser.NewLama2Parser()
fmt.Printf("apicontent %+v\n", apiContent)
fmt.Printf("WASM: apicontent %+v\n", apiContent)
parsedAPI, e := p.Parse(apiContent)
if e != nil {
fmt.Println("Error while parsing API:", e)
}

// Print the parsedAPI value
fmt.Printf("Parsed API: %+v\n", parsedAPI)
fmt.Printf("WASM: Parsed API: %+v\n", parsedAPI)
return HandleParsedFile(parsedAPI)
}

func ProcessConverterInput(data string, ConvertLang string) (string, error) {
fmt.Println("WASM: ProcessConverterInput")
apiContent := data
p := parser.NewLama2Parser()
parsedAPI, e := p.Parse(apiContent)
fmt.Println("Parsed API:", parsedAPI)
fmt.Println("WASM: Parsed API:", parsedAPI)
if e != nil {
fmt.Println("Error while parsing API:", e)
fmt.Println("WASM: Error while parsing API:", e)
}
snippet := codegen.GenerateTargetCode(ConvertLang, parsedAPI)
fmt.Println("Generated Snippet:", snippet)
fmt.Println("WASM: Generated Snippet:", snippet)
return snippet, nil
}

func ExecuteRequestorBlockHelper(resp httpie.ExResponse, headersString string, e1 error, vm interface{}) httpie.ExResponse {
fmt.Println("WASM: ExecuteRequestorBlockHelper")
targetHeader := "text/html"
isTextHTMLPresent := strings.Contains(headersString, targetHeader)
if isTextHTMLPresent {
fmt.Printf("'%s' is present in the headers.\n", targetHeader)
fmt.Printf("WASM: '%s' is present in the headers.\n", targetHeader)
return resp
} else {
fmt.Printf("'%s' is not present in the headers.\n", targetHeader)
fmt.Printf("WASM: '%s' is not present in the headers.\n", targetHeader)
if e1 == nil {
chainCode := cmdexec.GenerateChainCode(resp.Body)
preprocess.RunCodeInWorker(chainCode)
} else {
fmt.Println("Error from ExecCommand", e1)
fmt.Println("WASM: Error from ExecCommand", e1)
os.Exit(1)
}
}
return resp
}

func processBlocks(parsedAPIblocks []*gabs.Container, o *lama2cmd.Opts, dir string) (httpie.ExResponse, *lama2cmd.Opts, []outputmanager.ResponseTime, []outputmanager.StatusCode, []outputmanager.ContentSize, error) {
fmt.Println("WASM: processBlocks")
worker = preprocess.InitWebWorker() // Initialize the web worker
var resp httpie.ExResponse
for i, block := range parsedAPIblocks {
Expand All @@ -89,12 +93,15 @@ func processBlocks(parsedAPIblocks []*gabs.Container, o *lama2cmd.Opts, dir stri
resp, _, _ = processLama2FileBlock(block, worker, o, dir)
}
}
fmt.Println("WASM: processBlocks returning")
return resp, o, nil, nil, nil, nil
}

func ExecuteProcessorBlock(block *gabs.Container) {
fmt.Println("WASM: ExecuteProcessorBlock")
b := block.S("value").Data().(*gabs.Container)
log.Debug().Str("Processor block incoming block", block.String()).Msg("")
script := b.Data().(string)
preprocess.RunCodeInWorker(script)
fmt.Println("WASM: ExecuteProcessorBlock returning")
}
7 changes: 5 additions & 2 deletions l2.wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ func init() {
}

func main() {
fmt.Println("WASM: Starting main")
// Set the global JavaScript property "goWebRequestFunc" to the result of wasmLamaPromise
js.Global().Set("goWebRequestFunc", wasmLamaPromise())
js.Global().Set("goCmdConvertFunc", wasmCodeConverter())
Expand All @@ -29,9 +30,10 @@ func main() {
}

func wasmLamaPromise() js.Func {
fmt.Println("WASM: Creating wasmLamaPromise")
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
laBearerAuthToken := args[2].String()
js.Global().Set("LaBearerAuthToken", laBearerAuthToken)
liveapiManifest := args[2].String()
js.Global().Set("liveapiManifest", liveapiManifest)
inputdata := args[0].String()
handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
resolve := args[0]
Expand All @@ -52,6 +54,7 @@ func wasmLamaPromise() js.Func {
}

func wasmCodeConverter() js.Func {
fmt.Println("WASM: Creating wasmCodeConverter")
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
inputdata := args[0].String()
convertLang := args[1].String()
Expand Down
Loading