edge/pkg/module/context.go

96 lines
2.2 KiB
Go

package module
import (
"context"
"forge.cadoles.com/arcad/edge/pkg/app"
"forge.cadoles.com/arcad/edge/pkg/module/util"
"github.com/dop251/goja"
"github.com/pkg/errors"
)
type ContextKey string
const (
ContextKeySessionID ContextKey = "sessionId"
ContextKeyOriginRequest ContextKey = "originRequest"
)
type ContextModule struct{}
func (m *ContextModule) Name() string {
return "context"
}
func (m *ContextModule) new(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
return rt.ToValue(context.Background())
}
func (m *ContextModule) with(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
ctx := util.AssertContext(call.Argument(0), rt)
rawValues := util.AssertObject(call.Argument(1), rt)
values := make(map[ContextKey]any)
for k, v := range rawValues {
values[ContextKey(k)] = v
}
ctx = WithContext(ctx, values)
return rt.ToValue(ctx)
}
func (m *ContextModule) get(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
ctx := util.AssertContext(call.Argument(0), rt)
rawKey := util.AssertString(call.Argument(1), rt)
value := ctx.Value(ContextKey(rawKey))
return rt.ToValue(value)
}
func (m *ContextModule) Export(export *goja.Object) {
if err := export.Set("new", m.new); err != nil {
panic(errors.Wrap(err, "could not set 'new' function"))
}
if err := export.Set("get", m.get); err != nil {
panic(errors.Wrap(err, "could not set 'get' function"))
}
if err := export.Set("with", m.with); err != nil {
panic(errors.Wrap(err, "could not set 'with' function"))
}
if err := export.Set("ORIGIN_REQUEST", string(ContextKeyOriginRequest)); err != nil {
panic(errors.Wrap(err, "could not set 'ORIGIN_REQUEST' property"))
}
if err := export.Set("SESSION_ID", string(ContextKeySessionID)); err != nil {
panic(errors.Wrap(err, "could not set 'SESSION_ID' property"))
}
}
func ContextModuleFactory() app.ServerModuleFactory {
return func(server *app.Server) app.ServerModule {
return &ContextModule{}
}
}
func ContextValue[T any](ctx context.Context, key ContextKey) T {
value, ok := ctx.Value(key).(T)
if !ok {
return *new(T)
}
return value
}
func WithContext(ctx context.Context, values map[ContextKey]any) context.Context {
for k, v := range values {
ctx = context.WithValue(ctx, k, v)
}
return ctx
}