<repo_name>spirit-component/goja<file_sep>/fbp.go
package goja

import (
	"github.com/go-spirit/spirit/mail"

	"github.com/go-spirit/spirit/worker/fbp/protocol"
)

type fbp struct {
	session mail.Session
}

func (p *fbp) NewError(namespace string, code int, message string) error {
	return &protocol.Error{
		Code:        int64(code),
		Namespace:   namespace,
		Description: message,
	}
}

func (p *fbp) SetError(namespace string, code int, message string) {
	p.session.Payload().Content().SetError(
		&protocol.Error{
			Code:        int64(code),
			Namespace:   namespace,
			Description: message,
		},
	)
}

func (p *fbp) SetBody(body interface{}) error {
	return p.session.Payload().Content().SetBody(body)
}

func (p *fbp) Object() map[string]interface{} {
	v := make(map[string]interface{})
	err := p.session.Payload().Content().ToObject(&v)
	if err != nil {
		return nil
	}

	return v
}
<file_sep>/goja.go
package goja

import (
	crand "crypto/rand"
	"encoding/binary"
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"os"
	"path/filepath"
	"time"

	"github.com/dop251/goja"
	"github.com/dop251/goja_nodejs/console"
	"github.com/dop251/goja_nodejs/require"

	"github.com/go-spirit/spirit/component"
	"github.com/go-spirit/spirit/mail"
	"github.com/go-spirit/spirit/worker"
	"github.com/gogap/config"
	"github.com/spirit-component/goja/modules"
)

type Goja struct {
	alias string
	opts  component.Options
	conf  config.Configuration

	jsDir   string
	timeout time.Duration
}

func init() {
	component.RegisterComponent("goja", NewGoja)
}

func NewGoja(alias string, opts ...component.Option) (comp component.Component, err error) {

	compOpts := component.Options{}

	for _, o := range opts {
		o(&compOpts)
	}

	dir := compOpts.Config.GetString("dir")
	if len(dir) == 0 {
		err = errors.New("javascript dir is empty")
		return
	}

	fi, err := os.Stat(dir)
	if err != nil {
		return
	}

	if !fi.IsDir() {
		err = fmt.Errorf("path '%s' should be a folder", dir)
		return
	}

	g := &Goja{
		alias:   alias,
		opts:    compOpts,
		conf:    compOpts.Config,
		jsDir:   dir,
		timeout: compOpts.Config.GetTimeDuration("timeout", time.Second*30),
	}

	return g, nil
}

func (p *Goja) Start() error {
	return nil
}

func (p *Goja) Stop() error {
	return nil
}

func (p *Goja) Alias() string {
	if p == nil {
		return ""
	}

	return p.alias
}

func (p *Goja) Route(session mail.Session) worker.HandlerFunc {
	return p.runJS
}

func (p *Goja) runJS(session mail.Session) (err error) {

	action := session.Query("action")
	dir := session.Query("dir")
	strTimeout := session.Query("timeout")
	version := session.Query("version")

	if len(dir) == 0 {
		dir = p.jsDir
	}

	timeout := p.timeout
	if len(strTimeout) > 0 {
		if dur, e := time.ParseDuration(strTimeout); e == nil {
			timeout = dur
		}
	}

	var apiJsFile string

	if len(version) == 0 {
		apiJsFile = filepath.Join(dir, action+".js")
	} else {
		apiJsFile = filepath.Join(dir, action+"_"+version+".js")
	}

	jsData, err := ioutil.ReadFile(apiJsFile)
	if err != nil {
		return
	}

	vm := newVM()
	golib := modules.NewGoLib(vm)

	golib.Import("utils")
	golib.Import("log")

	vm.Set("session", session)
	vm.Set("caches", p.opts.Caches)
	vm.Set("config", p.opts.Config)
	vm.Set("go", golib)
	vm.Set("fbp", &fbp{session})

	prg, err := goja.Compile(apiJsFile, string(jsData), false)
	if err != nil {
		return
	}

	time.AfterFunc(timeout, func() {
		vm.Interrupt("goja runtime execute timeout")

	})

	_, vmErr := vm.RunProgram(prg)

	if vmErr != nil {
		switch jsErr := vmErr.(type) {
		case *goja.Exception:
			err = fmt.Errorf("%v", jsErr.Value())
		case *goja.InterruptedError:
			err = fmt.Errorf("execute action: '%s' interrupted, %v", action, jsErr.Value())
		default:
			err = vmErr
		}
	}

	return
}

func newVM() *goja.Runtime {
	vm := goja.New()
	vm.SetRandSource(newRandSource())
	new(require.Registry).Enable(vm)
	console.Enable(vm)
	return vm
}

func newRandSource() goja.RandSource {
	var seed int64
	if err := binary.Read(crand.Reader, binary.LittleEndian, &seed); err != nil {
		panic(fmt.Errorf("Could not read random bytes: %v", err))
	}
	return rand.New(rand.NewSource(seed)).Float64
}
<file_sep>/modules/modules.go
package modules

import (
	"fmt"

	"github.com/dop251/goja"
)

import (
	"github.com/spirit-component/goja/modules/crypto/md5"
	"github.com/spirit-component/goja/modules/encoding/base64"
	"github.com/spirit-component/goja/modules/encoding/json"
	jsfmt "github.com/spirit-component/goja/modules/fmt"
	"github.com/spirit-component/goja/modules/io/ioutil"
	"github.com/spirit-component/goja/modules/os"
	"github.com/spirit-component/goja/modules/os/exec"
	"github.com/spirit-component/goja/modules/time"

	"github.com/spirit-component/goja/modules/utils"

	"github.com/spirit-component/goja/modules/github.com/go-redis/redis"
	"github.com/spirit-component/goja/modules/github.com/google/uuid"
	"github.com/spirit-component/goja/modules/github.com/sirupsen/logrus"
)

var (
	golibs = map[string]func(runtime *goja.Runtime){
		"crypto/md5":      md5.Enable,
		"encoding/base64": base64.Enable,
		"encoding/json":   json.Enable,
		"fmt":             jsfmt.Enable,
		"time":            time.Enable,
		"uuid":            uuid.Enable,
		"io/ioutil":       ioutil.Enable,
		"utils":           utils.Enable,
		"os":              os.Enable,
		"os/exec":         exec.Enable,
		"redis":           redis.Enable,
		"log":             logrus.Enable,
	}
)

func RegisterNativeModule(importPath string, enableFunc func(runtime *goja.Runtime)) (err error) {
	if len(importPath) == 0 {
		err = fmt.Errorf("import path could not be empty")
		return
	}

	if enableFunc == nil {
		err = fmt.Errorf("register EnableFunc could not be nil, path: %s", importPath)
		return
	}

	golibs[importPath] = enableFunc

	return
}

type GoLib struct {
	vm *goja.Runtime
}

func NewGoLib(vm *goja.Runtime) *GoLib {
	return &GoLib{vm}
}

func (p *GoLib) Import(modules ...string) {
	if len(modules) == 0 {
		return
	}

	var loadFns []func(runtime *goja.Runtime)

	for _, module := range modules {
		fn, exist := golibs[module]
		if !exist {
			panic(fmt.Errorf("module of '%s' dost not exist", module))
		}

		loadFns = append(loadFns, fn)
	}

	for i := 0; i < len(loadFns); i++ {
		loadFns[i](p.vm)
	}
}
<file_sep>/modules/encoding/json/json.go
package json

import (
	original_json "encoding/json"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("json")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"Compact":       original_json.Compact,
			"HTMLEscape":    original_json.HTMLEscape,
			"Indent":        original_json.Indent,
			"Marshal":       original_json.Marshal,
			"MarshalIndent": original_json.MarshalIndent,
			"NewDecoder":    original_json.NewDecoder,
			"NewEncoder":    original_json.NewEncoder,
			"Unmarshal":     original_json.Unmarshal,
			"Valid":         original_json.Valid,

			// Var and consts

			// Types (value type)
			"Decoder":               func() original_json.Decoder { return original_json.Decoder{} },
			"Encoder":               func() original_json.Encoder { return original_json.Encoder{} },
			"InvalidUTF8Error":      func() original_json.InvalidUTF8Error { return original_json.InvalidUTF8Error{} },
			"InvalidUnmarshalError": func() original_json.InvalidUnmarshalError { return original_json.InvalidUnmarshalError{} },
			"MarshalerError":        func() original_json.MarshalerError { return original_json.MarshalerError{} },
			"SyntaxError":           func() original_json.SyntaxError { return original_json.SyntaxError{} },
			"UnmarshalFieldError":   func() original_json.UnmarshalFieldError { return original_json.UnmarshalFieldError{} },
			"UnmarshalTypeError":    func() original_json.UnmarshalTypeError { return original_json.UnmarshalTypeError{} },
			"UnsupportedTypeError":  func() original_json.UnsupportedTypeError { return original_json.UnsupportedTypeError{} },
			"UnsupportedValueError": func() original_json.UnsupportedValueError { return original_json.UnsupportedValueError{} },

			// Types (pointer type)
			"NewInvalidUTF8Error":      func() *original_json.InvalidUTF8Error { return &original_json.InvalidUTF8Error{} },
			"NewInvalidUnmarshalError": func() *original_json.InvalidUnmarshalError { return &original_json.InvalidUnmarshalError{} },
			"NewMarshalerError":        func() *original_json.MarshalerError { return &original_json.MarshalerError{} },
			"NewSyntaxError":           func() *original_json.SyntaxError { return &original_json.SyntaxError{} },
			"NewUnmarshalFieldError":   func() *original_json.UnmarshalFieldError { return &original_json.UnmarshalFieldError{} },
			"NewUnmarshalTypeError":    func() *original_json.UnmarshalTypeError { return &original_json.UnmarshalTypeError{} },
			"NewUnsupportedTypeError":  func() *original_json.UnsupportedTypeError { return &original_json.UnsupportedTypeError{} },
			"NewUnsupportedValueError": func() *original_json.UnsupportedValueError { return &original_json.UnsupportedValueError{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/README.md
goja
----

**component of goja**


#### build-config

```bash
> go-spirit pull --config build-goja.conf
> go-spirit build --config build-goja.conf
```

`build-goja.conf`

> working with post-api

```hocon
# project
goja  {

	# import packages
	packages = ["github.com/spirit-component/goja", "github.com/spirit-component/postapi"]

	build-args = {
		go-get = ["-v"]
		go-build = ["-v"]
	}

	fetchers {
		git {
			gopath = ${GOPATH}
		}
		goget {
			gopath = ${GOPATH}
		}
	}


	# the dependencies
	repos = {
		goja {
			fetcher = goget
			args = ["-v"]
			url = "github.com/spirit-component/goja"
			revision = master
		}

		postapi {
			fetcher = goget
			args = ["-v"]
			url = "github.com/spirit-component/postapi"
			revision = master
		}
	}
}
```


#### run config

```bash
> ./goja run --config goja.conf
```


`goja.conf`

```hocon

# goja config
components.goja.api-mock {
	dir = "scripts/"
	timeout = 3s
}

# post-api graph config
# default graph driver
components.post-api.external.grapher.default = {

	todo-task-new {
		name  = "todo.task.new"
		graph = {
			error {
				response {
					seq = 1
					url = "spirit://actors/fbp/post-api/external?action=callback"
				}
			}
			entrypoint {
				to-todo {
					seq = 1
					url = "spirit://actors/fbp/goja/api-mock?action=todo.task.new"
				}

				response {
					seq = 2
					url = "spirit://actors/fbp/post-api/external?action=callback"
				}
			}
		}
	}
}

```


```
# if you just want mapping api to js, you can use templer grapher
# the template file is json format, and it will render by text/template to replace some vars.

{
    "error": {
        "ports": [{
            "seq": 1,
            "url": "spirit://actors/fbp/post-api/external?action=callback"
        }]
    },
    "entrypoint": {
        "ports": [{
            "seq": 1,
            "url": "spirit://actors/fbp/goja/api-mock?action={{.api}}"
        },{
            "seq": 2,
            "url": "spirit://actors/fbp/post-api/external?action=callback"
        }]
    }
}

```
> before using `templer` grapher, you should append `"github.com/spirit-component/postapi/grapher/templer"` to config of `packages` list in `build-goja.conf`
and rebuild goja component


#### javascript

`scripts/todo.task.new.js`

```javascript
go.Import("uuid")
go.Import("fmt")
go.Import("time", "encoding/base64")


log.Infoln("hello I am the logger by logrus")

id = uuid.New()
obj = fbp.Object()
cache.Set(id, {id: id, name: obj.name})
fbp.SetBody({id: id})
```

`scripts/todo.task.get.js`

```javascript
obj = fbp.Object()

if (obj) {
	ret = cache.Get(obj.id)
	if (ret[1]) {
		fbp.SetBody(ret[0])
	} else {
		fbp.SetError("SPIRIT-GOJA",404,"task not exist")
	}
} else {
	fbp.SetError("SPIRIT-GOJA",400,"bad request")
}
```



### javascript

#### vars

name|type
:--|:--
session|github.com/go-spirit/spirit/mail.Session
cache|github.com/go-spirit/spirit/cache.Cache
config|github.com/gogap/config.Configuration
go|github.com/spirit-component/goja/modules.GoLib
fbp|github.com/spirit-component/goja.fbp


#### golibs

name |import path | repositry | default imported
:--|:--|:--|:--
md5 | `crypto/md5`||false
base64 | `encoding/base64`||false
json | `encoding/json`||false
fmt | `fmt`||false
uuid | `uuid`| `github.com/pborman/uuid`|false
ioutil|`io/ioutil`||false
os|`os`||false
exec|`os/exec`||false
time|`time`||false
redis|`redis`| `github.com/go-redis/redis`|false
log|`log`| `github.com/sirupsen/logrus`|true
utils|`utils`|`internal`|true




#### import lib in javascript

```javascript
go.Import("uuid")
go.Import("fmt")
go.Import("time", "encoding/base64")


log.Infoln("hello I am the logger by logrus")

id = uuid.New()
fbp.SetBody({id: id})

fmt.Println(base64.StdEncoding.EncodeToString("hello"))
```


#### generate your own native go module to javascript module

my another project is: [gojs-tool](https://github.com/gogap/gojs-tool), use this command to generate the module bridge

- generate moudle

```bash
# Default GOPATH
gojs-tool gen --template goja -r -n github.com/go-redis/redis

# GO Internal LIBs
gojs-tool gen --gopath $(go env GOROOT) --template goja -r -n encoding/json
```

- update generated code, add import `github.com/spirit-component/goja/modules` and add `modules.RegisterNativeModule` at `func init()`

```go
package your_package_name

import (
	// ....
	"github.com/spirit-component/goja/modules"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
   // the package name should be better equals to the "import/path/at/js" 's last slash name
   // here is js
	module = gojs.NewGojaModule("you_package_name")
)

func init() {
	// .........
	modules.RegisterNativeModule("import/path/at/js", Enable)
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
```

- update `build-goja.conf`

```
goja  {
	# append the generated module path
	packages = [..., "your_native_package_path"]
}
```
<file_sep>/modules/time/time.go
package time

import (
	original_time "time"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("time")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"After":           original_time.After,
			"AfterFunc":       original_time.AfterFunc,
			"Date":            original_time.Date,
			"FixedZone":       original_time.FixedZone,
			"LoadLocation":    original_time.LoadLocation,
			"NewTicker":       original_time.NewTicker,
			"NewTimer":        original_time.NewTimer,
			"Now":             original_time.Now,
			"Parse":           original_time.Parse,
			"ParseDuration":   original_time.ParseDuration,
			"ParseInLocation": original_time.ParseInLocation,
			"Since":           original_time.Since,
			"Sleep":           original_time.Sleep,
			"Tick":            original_time.Tick,
			"Unix":            original_time.Unix,
			"Until":           original_time.Until,

			// Var and consts
			"ANSIC":       original_time.ANSIC,
			"April":       original_time.April,
			"August":      original_time.August,
			"December":    original_time.December,
			"February":    original_time.February,
			"Friday":      original_time.Friday,
			"Hour":        original_time.Hour,
			"January":     original_time.January,
			"July":        original_time.July,
			"June":        original_time.June,
			"Kitchen":     original_time.Kitchen,
			"Local":       original_time.Local,
			"March":       original_time.March,
			"May":         original_time.May,
			"Microsecond": original_time.Microsecond,
			"Millisecond": original_time.Millisecond,
			"Minute":      original_time.Minute,
			"Monday":      original_time.Monday,
			"Nanosecond":  original_time.Nanosecond,
			"November":    original_time.November,
			"October":     original_time.October,
			"RFC1123":     original_time.RFC1123,
			"RFC1123Z":    original_time.RFC1123Z,
			"RFC3339":     original_time.RFC3339,
			"RFC3339Nano": original_time.RFC3339Nano,
			"RFC822":      original_time.RFC822,
			"RFC822Z":     original_time.RFC822Z,
			"RFC850":      original_time.RFC850,
			"RubyDate":    original_time.RubyDate,
			"Saturday":    original_time.Saturday,
			"Second":      original_time.Second,
			"September":   original_time.September,
			"Stamp":       original_time.Stamp,
			"StampMicro":  original_time.StampMicro,
			"StampMilli":  original_time.StampMilli,
			"StampNano":   original_time.StampNano,
			"Sunday":      original_time.Sunday,
			"Thursday":    original_time.Thursday,
			"Tuesday":     original_time.Tuesday,
			"UTC":         original_time.UTC,
			"UnixDate":    original_time.UnixDate,
			"Wednesday":   original_time.Wednesday,

			// Types (value type)
			"Location":   func() original_time.Location { return original_time.Location{} },
			"ParseError": func() original_time.ParseError { return original_time.ParseError{} },
			"Ticker":     func() original_time.Ticker { return original_time.Ticker{} },
			"Time":       func() original_time.Time { return original_time.Time{} },
			"Timer":      func() original_time.Timer { return original_time.Timer{} },

			// Types (pointer type)
			"NewLocation":   func() *original_time.Location { return &original_time.Location{} },
			"NewParseError": func() *original_time.ParseError { return &original_time.ParseError{} },
			"NewTime":       func() *original_time.Time { return &original_time.Time{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/utils/utils.go
package utils

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

func isNil(v interface{}) bool {
	return v == nil
}

var (
	module = gojs.NewGojaModule("utils")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"IsNil": isNil,
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/github.com/google/uuid/uuid.go
package uuid

import (
	original_uuid "github.com/google/uuid"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("uuid")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"ClockSequence":       original_uuid.ClockSequence,
			"FromBytes":           original_uuid.FromBytes,
			"GetTime":             original_uuid.GetTime,
			"Must":                original_uuid.Must,
			"MustParse":           original_uuid.MustParse,
			"New":                 original_uuid.New,
			"NewDCEGroup":         original_uuid.NewDCEGroup,
			"NewDCEPerson":        original_uuid.NewDCEPerson,
			"NewDCESecurity":      original_uuid.NewDCESecurity,
			"NewHash":             original_uuid.NewHash,
			"NewMD5":              original_uuid.NewMD5,
			"NewRandom":           original_uuid.NewRandom,
			"NewRandomFromReader": original_uuid.NewRandomFromReader,
			"NewSHA1":             original_uuid.NewSHA1,
			"NewUUID":             original_uuid.NewUUID,
			"NodeID":              original_uuid.NodeID,
			"NodeInterface":       original_uuid.NodeInterface,
			"Parse":               original_uuid.Parse,
			"ParseBytes":          original_uuid.ParseBytes,
			"SetClockSequence":    original_uuid.SetClockSequence,
			"SetNodeID":           original_uuid.SetNodeID,
			"SetNodeInterface":    original_uuid.SetNodeInterface,
			"SetRand":             original_uuid.SetRand,

			// Var and consts
			"Future":        original_uuid.Future,
			"Group":         original_uuid.Group,
			"Invalid":       original_uuid.Invalid,
			"Microsoft":     original_uuid.Microsoft,
			"NameSpaceDNS":  original_uuid.NameSpaceDNS,
			"NameSpaceOID":  original_uuid.NameSpaceOID,
			"NameSpaceURL":  original_uuid.NameSpaceURL,
			"NameSpaceX500": original_uuid.NameSpaceX500,
			"Nil":           original_uuid.Nil,
			"Org":           original_uuid.Org,
			"Person":        original_uuid.Person,
			"RFC4122":       original_uuid.RFC4122,
			"Reserved":      original_uuid.Reserved,

			// Types (value type)

			// Types (pointer type)
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/fmt/fmt.go
package fmt

import (
	original_fmt "fmt"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("fmt")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"Errorf":   original_fmt.Errorf,
			"Fprint":   original_fmt.Fprint,
			"Fprintf":  original_fmt.Fprintf,
			"Fprintln": original_fmt.Fprintln,
			"Fscan":    original_fmt.Fscan,
			"Fscanf":   original_fmt.Fscanf,
			"Fscanln":  original_fmt.Fscanln,
			"Print":    original_fmt.Print,
			"Printf":   original_fmt.Printf,
			"Println":  original_fmt.Println,
			"Scan":     original_fmt.Scan,
			"Scanf":    original_fmt.Scanf,
			"Scanln":   original_fmt.Scanln,
			"Sprint":   original_fmt.Sprint,
			"Sprintf":  original_fmt.Sprintf,
			"Sprintln": original_fmt.Sprintln,
			"Sscan":    original_fmt.Sscan,
			"Sscanf":   original_fmt.Sscanf,
			"Sscanln":  original_fmt.Sscanln,

			// Var and consts

			// Types (value type)

			// Types (pointer type)
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/encoding/base64/base64.go
package base64

import (
	original_base64 "encoding/base64"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("base64")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"NewDecoder":  original_base64.NewDecoder,
			"NewEncoder":  original_base64.NewEncoder,
			"NewEncoding": original_base64.NewEncoding,

			// Var and consts
			"NoPadding":      original_base64.NoPadding,
			"RawStdEncoding": original_base64.RawStdEncoding,
			"RawURLEncoding": original_base64.RawURLEncoding,
			"StdEncoding":    original_base64.StdEncoding,
			"StdPadding":     original_base64.StdPadding,
			"URLEncoding":    original_base64.URLEncoding,

			// Types (value type)
			"Encoding": func() original_base64.Encoding { return original_base64.Encoding{} },

			// Types (pointer type)
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/os/exec/exec.go
package exec

import (
	original_exec "os/exec"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("exec")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"Command":        original_exec.Command,
			"CommandContext": original_exec.CommandContext,
			"LookPath":       original_exec.LookPath,

			// Var and consts
			"ErrNotFound": original_exec.ErrNotFound,

			// Types (value type)
			"Cmd":       func() original_exec.Cmd { return original_exec.Cmd{} },
			"Error":     func() original_exec.Error { return original_exec.Error{} },
			"ExitError": func() original_exec.ExitError { return original_exec.ExitError{} },

			// Types (pointer type)
			"NewCmd":       func() *original_exec.Cmd { return &original_exec.Cmd{} },
			"NewError":     func() *original_exec.Error { return &original_exec.Error{} },
			"NewExitError": func() *original_exec.ExitError { return &original_exec.ExitError{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/github.com/go-redis/redis/redis.go
package redis

import (
	original_redis "github.com/go-redis/redis"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("redis")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"NewBoolCmd":               original_redis.NewBoolCmd,
			"NewBoolResult":            original_redis.NewBoolResult,
			"NewBoolSliceCmd":          original_redis.NewBoolSliceCmd,
			"NewBoolSliceResult":       original_redis.NewBoolSliceResult,
			"NewClient":                original_redis.NewClient,
			"NewClusterClient":         original_redis.NewClusterClient,
			"NewClusterSlotsCmd":       original_redis.NewClusterSlotsCmd,
			"NewClusterSlotsCmdResult": original_redis.NewClusterSlotsCmdResult,
			"NewCmd":                   original_redis.NewCmd,
			"NewCmdResult":             original_redis.NewCmdResult,
			"NewCommandsInfoCmd":       original_redis.NewCommandsInfoCmd,
			"NewCommandsInfoCmdResult": original_redis.NewCommandsInfoCmdResult,
			"NewDurationCmd":           original_redis.NewDurationCmd,
			"NewDurationResult":        original_redis.NewDurationResult,
			"NewFailoverClient":        original_redis.NewFailoverClient,
			"NewFloatCmd":              original_redis.NewFloatCmd,
			"NewFloatResult":           original_redis.NewFloatResult,
			"NewGeoLocationCmd":        original_redis.NewGeoLocationCmd,
			"NewGeoLocationCmdResult":  original_redis.NewGeoLocationCmdResult,
			"NewGeoPosCmd":             original_redis.NewGeoPosCmd,
			"NewIntCmd":                original_redis.NewIntCmd,
			"NewIntResult":             original_redis.NewIntResult,
			"NewRing":                  original_redis.NewRing,
			"NewScanCmd":               original_redis.NewScanCmd,
			"NewScanCmdResult":         original_redis.NewScanCmdResult,
			"NewScript":                original_redis.NewScript,
			"NewSliceCmd":              original_redis.NewSliceCmd,
			"NewSliceResult":           original_redis.NewSliceResult,
			"NewStatusCmd":             original_redis.NewStatusCmd,
			"NewStatusResult":          original_redis.NewStatusResult,
			"NewStringCmd":             original_redis.NewStringCmd,
			"NewStringIntMapCmd":       original_redis.NewStringIntMapCmd,
			"NewStringIntMapCmdResult": original_redis.NewStringIntMapCmdResult,
			"NewStringResult":          original_redis.NewStringResult,
			"NewStringSliceCmd":        original_redis.NewStringSliceCmd,
			"NewStringSliceResult":     original_redis.NewStringSliceResult,
			"NewStringStringMapCmd":    original_redis.NewStringStringMapCmd,
			"NewStringStringMapResult": original_redis.NewStringStringMapResult,
			"NewStringStructMapCmd":    original_redis.NewStringStructMapCmd,
			"NewTimeCmd":               original_redis.NewTimeCmd,
			"NewUniversalClient":       original_redis.NewUniversalClient,
			"NewZSliceCmd":             original_redis.NewZSliceCmd,
			"NewZSliceCmdResult":       original_redis.NewZSliceCmdResult,
			"ParseURL":                 original_redis.ParseURL,
			"SetLogger":                original_redis.SetLogger,

			// Var and consts
			"Nil":         original_redis.Nil,
			"TxFailedErr": original_redis.TxFailedErr,

			// Types (value type)
			"BitCount":           func() original_redis.BitCount { return original_redis.BitCount{} },
			"BoolCmd":            func() original_redis.BoolCmd { return original_redis.BoolCmd{} },
			"BoolSliceCmd":       func() original_redis.BoolSliceCmd { return original_redis.BoolSliceCmd{} },
			"Client":             func() original_redis.Client { return original_redis.Client{} },
			"ClusterClient":      func() original_redis.ClusterClient { return original_redis.ClusterClient{} },
			"ClusterNode":        func() original_redis.ClusterNode { return original_redis.ClusterNode{} },
			"ClusterOptions":     func() original_redis.ClusterOptions { return original_redis.ClusterOptions{} },
			"ClusterSlot":        func() original_redis.ClusterSlot { return original_redis.ClusterSlot{} },
			"ClusterSlotsCmd":    func() original_redis.ClusterSlotsCmd { return original_redis.ClusterSlotsCmd{} },
			"Cmd":                func() original_redis.Cmd { return original_redis.Cmd{} },
			"CommandInfo":        func() original_redis.CommandInfo { return original_redis.CommandInfo{} },
			"CommandsInfoCmd":    func() original_redis.CommandsInfoCmd { return original_redis.CommandsInfoCmd{} },
			"Conn":               func() original_redis.Conn { return original_redis.Conn{} },
			"DurationCmd":        func() original_redis.DurationCmd { return original_redis.DurationCmd{} },
			"FailoverOptions":    func() original_redis.FailoverOptions { return original_redis.FailoverOptions{} },
			"FloatCmd":           func() original_redis.FloatCmd { return original_redis.FloatCmd{} },
			"GeoLocation":        func() original_redis.GeoLocation { return original_redis.GeoLocation{} },
			"GeoLocationCmd":     func() original_redis.GeoLocationCmd { return original_redis.GeoLocationCmd{} },
			"GeoPos":             func() original_redis.GeoPos { return original_redis.GeoPos{} },
			"GeoPosCmd":          func() original_redis.GeoPosCmd { return original_redis.GeoPosCmd{} },
			"GeoRadiusQuery":     func() original_redis.GeoRadiusQuery { return original_redis.GeoRadiusQuery{} },
			"IntCmd":             func() original_redis.IntCmd { return original_redis.IntCmd{} },
			"Message":            func() original_redis.Message { return original_redis.Message{} },
			"Options":            func() original_redis.Options { return original_redis.Options{} },
			"Pipeline":           func() original_redis.Pipeline { return original_redis.Pipeline{} },
			"Pong":               func() original_redis.Pong { return original_redis.Pong{} },
			"PubSub":             func() original_redis.PubSub { return original_redis.PubSub{} },
			"Ring":               func() original_redis.Ring { return original_redis.Ring{} },
			"RingOptions":        func() original_redis.RingOptions { return original_redis.RingOptions{} },
			"ScanCmd":            func() original_redis.ScanCmd { return original_redis.ScanCmd{} },
			"ScanIterator":       func() original_redis.ScanIterator { return original_redis.ScanIterator{} },
			"Script":             func() original_redis.Script { return original_redis.Script{} },
			"SliceCmd":           func() original_redis.SliceCmd { return original_redis.SliceCmd{} },
			"Sort":               func() original_redis.Sort { return original_redis.Sort{} },
			"StatusCmd":          func() original_redis.StatusCmd { return original_redis.StatusCmd{} },
			"StringCmd":          func() original_redis.StringCmd { return original_redis.StringCmd{} },
			"StringIntMapCmd":    func() original_redis.StringIntMapCmd { return original_redis.StringIntMapCmd{} },
			"StringSliceCmd":     func() original_redis.StringSliceCmd { return original_redis.StringSliceCmd{} },
			"StringStringMapCmd": func() original_redis.StringStringMapCmd { return original_redis.StringStringMapCmd{} },
			"StringStructMapCmd": func() original_redis.StringStructMapCmd { return original_redis.StringStructMapCmd{} },
			"Subscription":       func() original_redis.Subscription { return original_redis.Subscription{} },
			"TimeCmd":            func() original_redis.TimeCmd { return original_redis.TimeCmd{} },
			"Tx":                 func() original_redis.Tx { return original_redis.Tx{} },
			"UniversalOptions":   func() original_redis.UniversalOptions { return original_redis.UniversalOptions{} },
			"Z":                  func() original_redis.Z { return original_redis.Z{} },
			"ZRangeBy":           func() original_redis.ZRangeBy { return original_redis.ZRangeBy{} },
			"ZSliceCmd":          func() original_redis.ZSliceCmd { return original_redis.ZSliceCmd{} },
			"ZStore":             func() original_redis.ZStore { return original_redis.ZStore{} },

			// Types (pointer type)
			"NewBitCount":         func() *original_redis.BitCount { return &original_redis.BitCount{} },
			"NewClusterNode":      func() *original_redis.ClusterNode { return &original_redis.ClusterNode{} },
			"NewClusterOptions":   func() *original_redis.ClusterOptions { return &original_redis.ClusterOptions{} },
			"NewClusterSlot":      func() *original_redis.ClusterSlot { return &original_redis.ClusterSlot{} },
			"NewCommandInfo":      func() *original_redis.CommandInfo { return &original_redis.CommandInfo{} },
			"NewConn":             func() *original_redis.Conn { return &original_redis.Conn{} },
			"NewFailoverOptions":  func() *original_redis.FailoverOptions { return &original_redis.FailoverOptions{} },
			"NewGeoLocation":      func() *original_redis.GeoLocation { return &original_redis.GeoLocation{} },
			"NewGeoPos":           func() *original_redis.GeoPos { return &original_redis.GeoPos{} },
			"NewGeoRadiusQuery":   func() *original_redis.GeoRadiusQuery { return &original_redis.GeoRadiusQuery{} },
			"NewMessage":          func() *original_redis.Message { return &original_redis.Message{} },
			"NewOptions":          func() *original_redis.Options { return &original_redis.Options{} },
			"NewPipeline":         func() *original_redis.Pipeline { return &original_redis.Pipeline{} },
			"NewPong":             func() *original_redis.Pong { return &original_redis.Pong{} },
			"NewPubSub":           func() *original_redis.PubSub { return &original_redis.PubSub{} },
			"NewRingOptions":      func() *original_redis.RingOptions { return &original_redis.RingOptions{} },
			"NewScanIterator":     func() *original_redis.ScanIterator { return &original_redis.ScanIterator{} },
			"NewSort":             func() *original_redis.Sort { return &original_redis.Sort{} },
			"NewSubscription":     func() *original_redis.Subscription { return &original_redis.Subscription{} },
			"NewTx":               func() *original_redis.Tx { return &original_redis.Tx{} },
			"NewUniversalOptions": func() *original_redis.UniversalOptions { return &original_redis.UniversalOptions{} },
			"NewZ":                func() *original_redis.Z { return &original_redis.Z{} },
			"NewZRangeBy":         func() *original_redis.ZRangeBy { return &original_redis.ZRangeBy{} },
			"NewZStore":           func() *original_redis.ZStore { return &original_redis.ZStore{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/crypto/md5/md5.go
package md5

import (
	original_md5 "crypto/md5"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("md5")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"New": original_md5.New,
			"Sum": original_md5.Sum,

			// Var and consts
			"BlockSize": original_md5.BlockSize,
			"Size":      original_md5.Size,
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/github.com/sirupsen/logrus/hooks/hooks.go
package hooks

import (
	"github.com/dop251/goja"
	"github.com/dop251/goja_nodejs/require"
)

import (
	"github.com/spirit-component/goja/modules/github.com/sirupsen/logrus/hooks/syslog"
	"github.com/spirit-component/goja/modules/github.com/sirupsen/logrus/hooks/test"
)

type hooks struct {
	syslog *goja.Object
	test   *goja.Object
}

func init() {
	require.RegisterNativeModule("hooks", Require)
}

func Require(runtime *goja.Runtime, module *goja.Object) {

	pkg := &hooks{
		syslog: require.Require(runtime, "syslog").(*goja.Object),
		test:   require.Require(runtime, "test").(*goja.Object),
	}

	o := module.Get("exports").(*goja.Object)

	o.Set("syslog", pkg.syslog)
	o.Set("test", pkg.test)
}

func Enable(runtime *goja.Runtime) {
	syslog.Enable(runtime)
	test.Enable(runtime)

	runtime.Set("hooks", require.Require(runtime, "hooks"))
}
<file_sep>/modules/github.com/sirupsen/logrus/logrus.go
package logrus

import (
	original_logrus "github.com/sirupsen/logrus"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("log")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"AddHook":             original_logrus.AddHook,
			"Debug":               original_logrus.Debug,
			"Debugf":              original_logrus.Debugf,
			"Debugln":             original_logrus.Debugln,
			"Error":               original_logrus.Error,
			"Errorf":              original_logrus.Errorf,
			"Errorln":             original_logrus.Errorln,
			"Exit":                original_logrus.Exit,
			"Fatal":               original_logrus.Fatal,
			"Fatalf":              original_logrus.Fatalf,
			"Fatalln":             original_logrus.Fatalln,
			"GetLevel":            original_logrus.GetLevel,
			"Info":                original_logrus.Info,
			"Infof":               original_logrus.Infof,
			"Infoln":              original_logrus.Infoln,
			"New":                 original_logrus.New,
			"NewEntry":            original_logrus.NewEntry,
			"Panic":               original_logrus.Panic,
			"Panicf":              original_logrus.Panicf,
			"Panicln":             original_logrus.Panicln,
			"ParseLevel":          original_logrus.ParseLevel,
			"Print":               original_logrus.Print,
			"Printf":              original_logrus.Printf,
			"Println":             original_logrus.Println,
			"RegisterExitHandler": original_logrus.RegisterExitHandler,
			"SetFormatter":        original_logrus.SetFormatter,
			"SetLevel":            original_logrus.SetLevel,
			"SetOutput":           original_logrus.SetOutput,
			"StandardLogger":      original_logrus.StandardLogger,
			"Warn":                original_logrus.Warn,
			"Warnf":               original_logrus.Warnf,
			"Warning":             original_logrus.Warning,
			"Warningf":            original_logrus.Warningf,
			"Warningln":           original_logrus.Warningln,
			"Warnln":              original_logrus.Warnln,
			"WithError":           original_logrus.WithError,
			"WithField":           original_logrus.WithField,
			"WithFields":          original_logrus.WithFields,

			// Var and consts
			"AllLevels":     original_logrus.AllLevels,
			"DebugLevel":    original_logrus.DebugLevel,
			"ErrorKey":      original_logrus.ErrorKey,
			"ErrorLevel":    original_logrus.ErrorLevel,
			"FatalLevel":    original_logrus.FatalLevel,
			"FieldKeyLevel": original_logrus.FieldKeyLevel,
			"FieldKeyMsg":   original_logrus.FieldKeyMsg,
			"FieldKeyTime":  original_logrus.FieldKeyTime,
			"InfoLevel":     original_logrus.InfoLevel,
			"PanicLevel":    original_logrus.PanicLevel,
			"WarnLevel":     original_logrus.WarnLevel,

			// Types (value type)
			"Entry":         func() original_logrus.Entry { return original_logrus.Entry{} },
			"JSONFormatter": func() original_logrus.JSONFormatter { return original_logrus.JSONFormatter{} },
			"Logger":        func() original_logrus.Logger { return original_logrus.Logger{} },
			"MutexWrap":     func() original_logrus.MutexWrap { return original_logrus.MutexWrap{} },
			"TextFormatter": func() original_logrus.TextFormatter { return original_logrus.TextFormatter{} },

			// Types (pointer type)
			"NewJSONFormatter": func() *original_logrus.JSONFormatter { return &original_logrus.JSONFormatter{} },
			"NewLogger":        func() *original_logrus.Logger { return &original_logrus.Logger{} },
			"NewMutexWrap":     func() *original_logrus.MutexWrap { return &original_logrus.MutexWrap{} },
			"NewTextFormatter": func() *original_logrus.TextFormatter { return &original_logrus.TextFormatter{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/io/ioutil/ioutil.go
package ioutil

import (
	original_ioutil "io/ioutil"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("ioutil")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"NopCloser": original_ioutil.NopCloser,
			"ReadAll":   original_ioutil.ReadAll,
			"ReadDir":   original_ioutil.ReadDir,
			"ReadFile":  original_ioutil.ReadFile,
			"TempDir":   original_ioutil.TempDir,
			"TempFile":  original_ioutil.TempFile,
			"WriteFile": original_ioutil.WriteFile,

			// Var and consts
			"Discard": original_ioutil.Discard,

			// Types (value type)

			// Types (pointer type)
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/os/os.go
package os

import (
	original_os "os"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("os")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"Chdir":           original_os.Chdir,
			"Chmod":           original_os.Chmod,
			"Chown":           original_os.Chown,
			"Chtimes":         original_os.Chtimes,
			"Clearenv":        original_os.Clearenv,
			"Create":          original_os.Create,
			"Environ":         original_os.Environ,
			"Executable":      original_os.Executable,
			"Exit":            original_os.Exit,
			"Expand":          original_os.Expand,
			"ExpandEnv":       original_os.ExpandEnv,
			"FindProcess":     original_os.FindProcess,
			"Getegid":         original_os.Getegid,
			"Getenv":          original_os.Getenv,
			"Geteuid":         original_os.Geteuid,
			"Getgid":          original_os.Getgid,
			"Getgroups":       original_os.Getgroups,
			"Getpagesize":     original_os.Getpagesize,
			"Getpid":          original_os.Getpid,
			"Getppid":         original_os.Getppid,
			"Getuid":          original_os.Getuid,
			"Getwd":           original_os.Getwd,
			"Hostname":        original_os.Hostname,
			"IsExist":         original_os.IsExist,
			"IsNotExist":      original_os.IsNotExist,
			"IsPathSeparator": original_os.IsPathSeparator,
			"IsPermission":    original_os.IsPermission,
			"Lchown":          original_os.Lchown,
			"Link":            original_os.Link,
			"LookupEnv":       original_os.LookupEnv,
			"Lstat":           original_os.Lstat,
			"Mkdir":           original_os.Mkdir,
			"MkdirAll":        original_os.MkdirAll,
			"NewFile":         original_os.NewFile,
			"NewSyscallError": original_os.NewSyscallError,
			"Open":            original_os.Open,
			"OpenFile":        original_os.OpenFile,
			"Pipe":            original_os.Pipe,
			"Readlink":        original_os.Readlink,
			"Remove":          original_os.Remove,
			"RemoveAll":       original_os.RemoveAll,
			"Rename":          original_os.Rename,
			"SameFile":        original_os.SameFile,
			"Setenv":          original_os.Setenv,
			"StartProcess":    original_os.StartProcess,
			"Stat":            original_os.Stat,
			"Symlink":         original_os.Symlink,
			"TempDir":         original_os.TempDir,
			"Truncate":        original_os.Truncate,
			"Unsetenv":        original_os.Unsetenv,

			// Var and consts
			"Args":              original_os.Args,
			"DevNull":           original_os.DevNull,
			"ErrClosed":         original_os.ErrClosed,
			"ErrExist":          original_os.ErrExist,
			"ErrInvalid":        original_os.ErrInvalid,
			"ErrNotExist":       original_os.ErrNotExist,
			"ErrPermission":     original_os.ErrPermission,
			"Interrupt":         original_os.Interrupt,
			"Kill":              original_os.Kill,
			"ModeAppend":        original_os.ModeAppend,
			"ModeCharDevice":    original_os.ModeCharDevice,
			"ModeDevice":        original_os.ModeDevice,
			"ModeDir":           original_os.ModeDir,
			"ModeExclusive":     original_os.ModeExclusive,
			"ModeNamedPipe":     original_os.ModeNamedPipe,
			"ModePerm":          original_os.ModePerm,
			"ModeSetgid":        original_os.ModeSetgid,
			"ModeSetuid":        original_os.ModeSetuid,
			"ModeSocket":        original_os.ModeSocket,
			"ModeSticky":        original_os.ModeSticky,
			"ModeSymlink":       original_os.ModeSymlink,
			"ModeTemporary":     original_os.ModeTemporary,
			"ModeType":          original_os.ModeType,
			"O_APPEND":          original_os.O_APPEND,
			"O_CREATE":          original_os.O_CREATE,
			"O_EXCL":            original_os.O_EXCL,
			"O_RDONLY":          original_os.O_RDONLY,
			"O_RDWR":            original_os.O_RDWR,
			"O_SYNC":            original_os.O_SYNC,
			"O_TRUNC":           original_os.O_TRUNC,
			"O_WRONLY":          original_os.O_WRONLY,
			"PathListSeparator": original_os.PathListSeparator,
			"PathSeparator":     original_os.PathSeparator,
			"SEEK_CUR":          original_os.SEEK_CUR,
			"SEEK_END":          original_os.SEEK_END,
			"SEEK_SET":          original_os.SEEK_SET,
			"Stderr":            original_os.Stderr,
			"Stdin":             original_os.Stdin,
			"Stdout":            original_os.Stdout,

			// Types (value type)
			"File":         func() original_os.File { return original_os.File{} },
			"LinkError":    func() original_os.LinkError { return original_os.LinkError{} },
			"PathError":    func() original_os.PathError { return original_os.PathError{} },
			"ProcAttr":     func() original_os.ProcAttr { return original_os.ProcAttr{} },
			"Process":      func() original_os.Process { return original_os.Process{} },
			"ProcessState": func() original_os.ProcessState { return original_os.ProcessState{} },
			"SyscallError": func() original_os.SyscallError { return original_os.SyscallError{} },

			// Types (pointer type)
			"NewLinkError":    func() *original_os.LinkError { return &original_os.LinkError{} },
			"NewPathError":    func() *original_os.PathError { return &original_os.PathError{} },
			"NewProcAttr":     func() *original_os.ProcAttr { return &original_os.ProcAttr{} },
			"NewProcess":      func() *original_os.Process { return &original_os.Process{} },
			"NewProcessState": func() *original_os.ProcessState { return &original_os.ProcessState{} },
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
<file_sep>/modules/github.com/sirupsen/logrus/hooks/syslog/syslog.go
package syslog

import (
	original_syslog "github.com/sirupsen/logrus/hooks/syslog"
)

import (
	"github.com/dop251/goja"
	"github.com/gogap/gojs-tool/gojs"
)

var (
	module = gojs.NewGojaModule("syslog")
)

func init() {
	module.Set(
		gojs.Objects{
			// Functions
			"NewSyslogHook": original_syslog.NewSyslogHook,

			// Var and consts

			// Types (value type)
			"SyslogHook": func() original_syslog.SyslogHook { return original_syslog.SyslogHook{} },

			// Types (pointer type)
		},
	).Register()
}

func Enable(runtime *goja.Runtime) {
	module.Enable(runtime)
}
