Skip to content

Commit

Permalink
allow importing files in js plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
oq-x committed Sep 23, 2023
1 parent b876bb9 commit 048c484
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 33 deletions.
22 changes: 19 additions & 3 deletions server/plugins-js.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package server

import (
"fmt"
"os"

"github.com/dop251/goja"
"github.com/dynamitemc/dynamite/logger"
)

type PluginData struct {
type pluginConfiguration struct {
Identifier string `js:"identifier"`
}

Expand All @@ -32,7 +33,7 @@ func at[T any](arr []T, index int) (val T) {
return arr[index]
}

func getJavaScriptVM(logger logger.Logger, plugin *Plugin) *goja.Runtime {
func getJavaScriptVM(logger logger.Logger, plugin *Plugin, root string) *goja.Runtime {
vm := goja.New()
vm.SetFieldNameMapper(goja.TagFieldNameMapper("js", true))
server := vm.NewObject()
Expand Down Expand Up @@ -63,7 +64,7 @@ func getJavaScriptVM(logger logger.Logger, plugin *Plugin) *goja.Runtime {
logger.Print(format, a...)
})

vm.Set("Plugin", func(data *PluginData) {
vm.Set("Plugin", func(data *pluginConfiguration) {
if data == nil {
logger.Error("Failed to load plugin %s: invalid plugin data", plugin.Filename)
} else {
Expand All @@ -76,5 +77,20 @@ func getJavaScriptVM(logger logger.Logger, plugin *Plugin) *goja.Runtime {
})
server.Set("logger", log)
vm.Set("server", server)

vm.Set("require", func(file string) map[string]interface{} {
exports := make(map[string]interface{})
path := root + "/" + file
f, err := os.ReadFile(path)
if err != nil {
return exports
}
v := *vm
v.Set("exports", goja.Undefined())
v.RunString(string(f))
v.ExportTo(v.Get("exports"), &exports)
fmt.Println(v.Get("exports"))
return exports
})
return vm
}
133 changes: 103 additions & 30 deletions server/plugins.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package server

import (
"encoding/json"
"errors"
"fmt"
"io/fs"
Expand All @@ -11,14 +12,23 @@ import (
"github.com/dop251/goja"
)

var unrecognizedScript = errors.New("unrecognized scripting language")
var uninitalized = errors.New("plugin was not initialized")
var pluginUnrecognizedType = errors.New("unrecognized plugin type")
var pluginUninitalized = errors.New("plugin was not initialized")
var pluginNoData = errors.New("no plugin data found")
var pluginInvalidData = errors.New("failed to parse plugin data")
var pluginNoRoot = errors.New("no plugin root file")
var pluginSingleFile = errors.New("cannot import files in single file plugin")

const (
PluginTypeJavaScript = iota
PluginTypeLua
)

type pluginData struct {
RootFile string `json:"rootFile"`
Type string `json:"type"`
}

type Plugin struct {
Identifier string
Initialized bool
Expand Down Expand Up @@ -56,42 +66,105 @@ func (srv *Server) LoadPlugins() error {
}

func (srv *Server) LoadPlugin(path string) (*Plugin, error) {
file, err := os.ReadFile(path)
info, err := os.Stat(path)
if err != nil {
fmt.Println(err)
return nil, err
}
sp := strings.Split(path, "/")
filename := sp[len(sp)-1]
switch {
case strings.HasSuffix(path, ".js"):
{
plugin := &Plugin{Filename: filename, Type: PluginTypeJavaScript}
js := getJavaScriptVM(srv.Logger, plugin)
plugin.JSLoader = js
_, err := js.RunString(string(file))
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", filename, err)
return nil, err
if info.IsDir() {
file, err := os.ReadFile(path + "/plugin.json")
var data pluginData
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginNoData)
return nil, pluginNoData
}
err = json.Unmarshal(file, &data)
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginInvalidData)
return nil, pluginInvalidData
}
file, err = os.ReadFile(path + "/" + data.RootFile)
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginNoRoot)
return nil, pluginNoRoot
}
switch data.Type {
case "javascript":
{
plugin := &Plugin{Filename: info.Name(), Type: PluginTypeJavaScript}
js := getJavaScriptVM(srv.Logger, plugin, path)
plugin.JSLoader = js
_, err := js.RunString(string(file))
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), err)
return nil, err
}
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginUninitalized)
return nil, pluginUninitalized
}
return plugin, nil
}
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", filename, uninitalized)
return nil, uninitalized
case "lua":
{
plugin := &Plugin{Filename: info.Name(), Type: PluginTypeLua}
l := getLuaVM(srv.Logger, plugin)
plugin.LuaLoader = l
lua.DoString(l, string(file))
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginUninitalized)
return nil, pluginUninitalized
}
return plugin, nil
}
return plugin, nil
default:
{
srv.Logger.Error("Failed to load plugin %s: %s", info.Name(), pluginUnrecognizedType)
return nil, pluginUnrecognizedType
}
}
} else {
file, err := os.ReadFile(path)
if err != nil {
fmt.Println(err)
return nil, err
}
case strings.HasSuffix(path, ".lua"):
{
plugin := &Plugin{Filename: filename, Type: PluginTypeLua}
l := getLuaVM(srv.Logger, plugin)
plugin.LuaLoader = l
lua.DoString(l, string(file))
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", filename, uninitalized)
return nil, uninitalized
sp := strings.Split(path, "/")
filename := sp[len(sp)-1]
switch {
case strings.HasSuffix(path, ".js"):
{
plugin := &Plugin{Filename: filename, Type: PluginTypeJavaScript}
js := getJavaScriptVM(srv.Logger, plugin, "")
plugin.JSLoader = js
_, err := js.RunString(string(file))
if err != nil {
srv.Logger.Error("Failed to load plugin %s: %s", filename, err)
return nil, err
}
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", filename, pluginUninitalized)
return nil, pluginUninitalized
}
return plugin, nil
}
case strings.HasSuffix(path, ".lua"):
{
plugin := &Plugin{Filename: filename, Type: PluginTypeLua}
l := getLuaVM(srv.Logger, plugin)
plugin.LuaLoader = l
lua.DoString(l, string(file))
if !plugin.Initialized {
srv.Logger.Error("Failed to load plugin %s: %s", filename, pluginUninitalized)
return nil, pluginUninitalized
}
return plugin, nil
}
default:
{
srv.Logger.Error("Failed to load plugin %s: %s", filename, pluginUnrecognizedType)
return nil, pluginUnrecognizedType
}
return plugin, nil
}
}
return nil, nil
}

0 comments on commit 048c484

Please sign in to comment.