mirror of
https://github.com/jwetzell/showbridge-go.git
synced 2026-04-26 21:05:30 +00:00
138 lines
3.1 KiB
Go
138 lines
3.1 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/google/jsonschema-go/jsonschema"
|
|
"github.com/jwetzell/showbridge-go/internal/common"
|
|
"github.com/jwetzell/showbridge-go/internal/config"
|
|
"modernc.org/quickjs"
|
|
)
|
|
|
|
type ScriptJS struct {
|
|
config config.ProcessorConfig
|
|
vm *quickjs.VM
|
|
payloadAtom quickjs.Atom
|
|
senderAtom quickjs.Atom
|
|
Program string
|
|
}
|
|
|
|
func (sj *ScriptJS) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
|
|
|
|
//NOTE(jwetzell): some weird conversion going on with these types
|
|
_, isUint8Slice := common.GetAnyAs[[]uint8](wrappedPayload.Payload)
|
|
_, isByteSlice := common.GetAnyAs[[]byte](wrappedPayload.Payload)
|
|
|
|
if isUint8Slice || isByteSlice {
|
|
intSlice, ok := common.GetAnyAsIntSlice(wrappedPayload.Payload)
|
|
|
|
if ok {
|
|
wrappedPayload.Payload = intSlice
|
|
}
|
|
}
|
|
|
|
sj.vm.SetProperty(sj.vm.GlobalObject(), sj.payloadAtom, wrappedPayload.Payload)
|
|
|
|
sj.vm.SetProperty(sj.vm.GlobalObject(), sj.senderAtom, wrappedPayload.Sender)
|
|
|
|
_, err := sj.vm.Eval(sj.Program, quickjs.EvalGlobal)
|
|
|
|
if err != nil {
|
|
wrappedPayload.End = true
|
|
return wrappedPayload, err
|
|
}
|
|
|
|
output, err := sj.vm.GetProperty(sj.vm.GlobalObject(), sj.payloadAtom)
|
|
|
|
if err != nil {
|
|
wrappedPayload.End = true
|
|
return wrappedPayload, err
|
|
}
|
|
|
|
// NOTE(jwetzell): turn undefined into nil
|
|
_, ok := output.(quickjs.Undefined)
|
|
|
|
if ok {
|
|
wrappedPayload.End = true
|
|
wrappedPayload.Payload = nil
|
|
return wrappedPayload, nil
|
|
}
|
|
|
|
// NOTE(jwetzell): turn object into map[string]interface{}
|
|
outputObject, ok := output.(*quickjs.Object)
|
|
|
|
if ok {
|
|
var outputSlice []interface{}
|
|
|
|
err = outputObject.Into(&outputSlice)
|
|
|
|
if err != nil {
|
|
var outputMap map[string]interface{}
|
|
err = outputObject.Into(&outputMap)
|
|
if err != nil {
|
|
wrappedPayload.End = true
|
|
return wrappedPayload, err
|
|
} else {
|
|
wrappedPayload.Payload = outputMap
|
|
return wrappedPayload, nil
|
|
}
|
|
|
|
} else {
|
|
wrappedPayload.Payload = outputSlice
|
|
return wrappedPayload, nil
|
|
}
|
|
}
|
|
|
|
wrappedPayload.Payload = output
|
|
return wrappedPayload, nil
|
|
}
|
|
|
|
func (sj *ScriptJS) Type() string {
|
|
return sj.config.Type
|
|
}
|
|
|
|
func init() {
|
|
RegisterProcessor(ProcessorRegistration{
|
|
Type: "script.js",
|
|
Title: "Run JavaScript",
|
|
ParamsSchema: &jsonschema.Schema{
|
|
Type: "object",
|
|
Properties: map[string]*jsonschema.Schema{
|
|
"program": {
|
|
Title: "Program",
|
|
Type: "string",
|
|
},
|
|
},
|
|
Required: []string{"program"},
|
|
AdditionalProperties: &jsonschema.Schema{Not: &jsonschema.Schema{}},
|
|
},
|
|
New: func(config config.ProcessorConfig) (Processor, error) {
|
|
params := config.Params
|
|
|
|
programString, err := params.GetString("program")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("script.js program error: %w", err)
|
|
}
|
|
|
|
vm, err := quickjs.NewVM()
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
payloadAtom, err := vm.NewAtom("payload")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
senderAtom, err := vm.NewAtom("sender")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &ScriptJS{config: config, Program: programString, vm: vm, payloadAtom: payloadAtom, senderAtom: senderAtom}, nil
|
|
},
|
|
})
|
|
}
|