-
Notifications
You must be signed in to change notification settings - Fork 2
/
goja.go
130 lines (98 loc) · 2.24 KB
/
goja.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package goja
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"github.com/dop251/goja"
"github.com/temphia/temphia/code/backend/libx/easyerr"
"github.com/temphia/temphia/code/backend/xtypes/etypes/bindx"
"github.com/temphia/temphia/code/backend/xtypes/etypes/event"
"github.com/temphia/temphia/code/backend/xtypes/etypes"
)
var _ etypes.Executor = (*Goja)(nil)
type Goja struct {
runtime *goja.Runtime
binder bindx.Bindings
}
func NewBuilder(app any) (etypes.ExecutorBuilder, error) {
return etypes.ExecBuilderFunc(newExecutor), nil
}
func newExecutor(opts etypes.ExecutorOption) (etypes.Executor, error) {
script, _, err := opts.Binder.GetFileWithMeta(opts.File)
if err != nil {
return nil, err
}
rt := goja.New()
// fixme => snowflake
rt.SetRandSource(func() float64 {
fid := rand.Float64()
return fid
})
_, err = rt.RunProgram(libesplug)
if err != nil {
panic(err)
}
_, err = rt.RunString(string(script))
if err != nil {
return nil, err
}
return New(opts.Binder, rt)
}
func New(b bindx.Bindings, rt *goja.Runtime) (*Goja, error) {
g := &Goja{
runtime: rt,
binder: b,
}
g.bind()
_, err := rt.RunProgram(libesplug)
if err != nil {
return nil, err
}
return g, nil
}
type Response struct {
Payload any `json:"payload,omitempty"`
}
type Request struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Data any `json:"data,omitempty"`
}
func (g *Goja) Process(ev *event.Request) (*event.Response, error) {
var data any
if ev.Data != nil {
err := json.Unmarshal(ev.Data, &data)
if err != nil {
return nil, easyerr.Wrap("Cannot unmarshel request data", err)
}
}
var entry func(ev *Request) (goja.Value, error)
rawentry := g.runtime.Get(fmt.Sprintf("action_%s", ev.Name))
if rawentry == nil {
return nil, errors.New("method not found")
}
err := g.runtime.ExportTo(rawentry, &entry)
if err != nil {
return nil, err
}
resp := &event.Response{}
val, err := entry(&Request{
Id: ev.Id,
Name: ev.Name,
Data: data,
})
if err != nil {
return nil, err
}
if goja.IsNull(val) {
resp.Payload = []byte("null")
} else {
out, err := val.ToObject(g.runtime).MarshalJSON()
if err != nil {
return nil, err
}
resp.Payload = out
}
return resp, nil
}