Skip to content

Commit e16cf2b

Browse files
committed
refactor(plugin): refactor plugin
1 parent c8d1618 commit e16cf2b

File tree

24 files changed

+267
-218
lines changed

24 files changed

+267
-218
lines changed

admin/api/plugins.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ func (api *API) CreatePlugin(w http.ResponseWriter, r *http.Request) {
4444
return
4545
}
4646

47-
p, err := model.Plugin()
48-
api.assert(err)
49-
model.Config = utils.Must(p.MarshalConfig())
50-
err = api.db.PluginsWS.Insert(r.Context(), &model)
47+
err := api.db.PluginsWS.Insert(r.Context(), &model)
5148
api.assert(err)
5249

5350
api.json(201, w, model)
@@ -73,11 +70,6 @@ func (api *API) UpdatePlugin(w http.ResponseWriter, r *http.Request) {
7370
return
7471
}
7572

76-
p, err := model.Plugin()
77-
api.assert(err)
78-
79-
model.Config = utils.Must(p.MarshalConfig())
80-
8173
model.ID = id
8274
err = api.db.PluginsWS.Update(r.Context(), model)
8375
api.assert(err)

db/entities/plugin.go

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package entities
22

33
import (
4+
"database/sql/driver"
45
"encoding/json"
56
"errors"
67
"fmt"
@@ -44,11 +45,11 @@ func (m *Plugin) Validate() error {
4445
}
4546

4647
// validate plugin configuration
47-
p, err := m.Plugin()
48+
p, err := m.ToPlugin()
4849
if err != nil {
4950
return err
5051
}
51-
if err = p.ValidateConfig(); err != nil {
52+
if err = p.ValidateConfig(m.Config); err != nil {
5253
if e, ok := err.(*errs.ValidateError); ok {
5354
e.Fields = map[string]interface{}{
5455
"config": e.Fields,
@@ -57,6 +58,13 @@ func (m *Plugin) Validate() error {
5758
}
5859
return err
5960
}
61+
62+
err = p.Init(m.Config)
63+
if err != nil {
64+
return err
65+
}
66+
m.Config = p.GetConfig()
67+
6068
return nil
6169
}
6270

@@ -69,44 +77,40 @@ func (m *Plugin) UnmarshalJSON(data []byte) error {
6977
return json.Unmarshal(data, (*alias)(m))
7078
}
7179

72-
func (m *Plugin) Plugin() (plugin.Plugin, error) {
73-
r := plugin.GetRegistration(m.Name)
74-
if r == nil {
80+
func (m *Plugin) ToPlugin() (plugin.Plugin, error) {
81+
executor, ok := plugin.New(m.Name)
82+
if !ok {
7583
return nil, fmt.Errorf("unknown plugin name: '%s'", m.Name)
7684
}
77-
78-
executor, err := r.New(m.Config)
79-
if err != nil {
80-
return nil, err
81-
}
8285
return executor, nil
8386
}
8487

85-
type PluginConfiguration json.RawMessage
88+
type PluginConfiguration map[string]interface{}
8689

87-
func (m PluginConfiguration) MarshalYAML() (interface{}, error) {
88-
if len(m) == 0 {
89-
return nil, nil
90-
}
91-
data := make(map[string]interface{})
92-
err := json.Unmarshal(m, &data)
93-
if err != nil {
94-
return nil, err
90+
func (m PluginConfiguration) GetString(key string, def string) string {
91+
val, ok := m[key]
92+
if !ok {
93+
return def
9594
}
96-
return data, nil
95+
return val.(string)
9796
}
9897

99-
func (m PluginConfiguration) MarshalJSON() ([]byte, error) {
98+
func (m *PluginConfiguration) Scan(src interface{}) error {
99+
return json.Unmarshal(src.([]byte), m)
100+
}
101+
102+
func (m PluginConfiguration) Value() (driver.Value, error) {
100103
if m == nil {
101-
return []byte("null"), nil
104+
return []byte(`{}`), nil
102105
}
103-
return m, nil
106+
return json.Marshal(m)
104107
}
105108

106109
func (m *PluginConfiguration) UnmarshalJSON(data []byte) error {
107-
if m == nil {
108-
return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
110+
v := make(map[string]interface{})
111+
if err := json.Unmarshal(data, &v); err != nil {
112+
return err
109113
}
110-
*m = append((*m)[0:0], data...)
114+
*m = v
111115
return nil
112116
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ require (
6363
github.com/mailru/easyjson v0.7.7 // indirect
6464
github.com/mattn/go-colorable v0.1.13 // indirect
6565
github.com/mattn/go-isatty v0.0.19 // indirect
66+
github.com/mitchellh/mapstructure v1.5.0 // indirect
6667
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
6768
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
6869
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
170170
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
171171
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
172172
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
173+
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
174+
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
173175
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
174176
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
175177
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=

openapi.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ components:
936936
nullable: true
937937
config:
938938
type: object
939-
nullable: true
939+
default: {}
940940
metadata:
941941
$ref: "#/components/schemas/Metadata"
942942
created_at:
@@ -988,3 +988,33 @@ components:
988988
required:
989989
- quota
990990
- period
991+
992+
993+
WasmPluginConfiguration:
994+
type: object
995+
properties:
996+
file:
997+
type: string
998+
envs:
999+
type: object
1000+
additionalProperties:
1001+
type: string
1002+
default: { }
1003+
required:
1004+
- file
1005+
1006+
FunctionPluginConfiguration:
1007+
type: object
1008+
properties:
1009+
function:
1010+
type: string
1011+
maxLength: 1048576
1012+
required:
1013+
- function
1014+
1015+
WebhookxSignaturePluginConfiguration:
1016+
type: object
1017+
properties:
1018+
signing_secret:
1019+
type: string
1020+
minLength: 1

pkg/declarative/types.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ func (cfg *Configuration) Validate() error {
5454
if err := model.Validate(); err != nil {
5555
return err
5656
}
57-
p, err := model.Plugin()
58-
if err != nil {
59-
return err
60-
}
61-
model.Config = utils.Must(p.MarshalConfig())
6257
}
6358
}
6459

@@ -67,11 +62,6 @@ func (cfg *Configuration) Validate() error {
6762
if err := model.Validate(); err != nil {
6863
return err
6964
}
70-
p, err := model.Plugin()
71-
if err != nil {
72-
return err
73-
}
74-
model.Config = utils.Must(p.MarshalConfig())
7565
}
7666
}
7767

pkg/plugin/base.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package plugin
2+
3+
import (
4+
"context"
5+
"github.com/getkin/kin-openapi/openapi3"
6+
"github.com/mitchellh/mapstructure"
7+
"github.com/webhookx-io/webhookx/pkg/openapi"
8+
"github.com/webhookx-io/webhookx/utils"
9+
)
10+
11+
// Configuration plugin configuration
12+
type Configuration interface {
13+
Schema() *openapi3.Schema
14+
}
15+
16+
type BasePlugin[T Configuration] struct {
17+
Config T
18+
}
19+
20+
func (p *BasePlugin[T]) Init(config map[string]interface{}) error {
21+
return mapstructure.Decode(config, &p.Config)
22+
}
23+
24+
func (p *BasePlugin[T]) GetConfig() map[string]interface{} {
25+
m, err := utils.StructToMap(p.Config)
26+
if err != nil {
27+
panic(err)
28+
}
29+
return m
30+
}
31+
32+
func (p *BasePlugin[T]) ValidateConfig(config map[string]interface{}) error {
33+
err := openapi.Validate(p.Config.Schema(), config)
34+
if err != nil {
35+
return err
36+
}
37+
return nil
38+
}
39+
40+
func (p *BasePlugin[T]) ExecuteOutbound(ctx context.Context, outbound *Outbound) error {
41+
panic("not implemented")
42+
}
43+
44+
func (p *BasePlugin[T]) ExecuteInbound(ctx context.Context, inbound *Inbound) (InboundResult, error) {
45+
panic("not implemented")
46+
}

pkg/plugin/plugin.go

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11
package plugin
22

33
import (
4-
"encoding/json"
4+
"context"
55
"net/http"
66
)
77

88
type Plugin interface {
9-
ExecuteOutbound(outbound *Outbound, context *Context) error
10-
ExecuteInbound(inbound *Inbound) (InboundResult, error)
11-
ValidateConfig() error
12-
MarshalConfig() ([]byte, error)
13-
}
9+
// Name returns plugin's name
10+
Name() string
1411

15-
type BasePlugin[T any] struct {
16-
Name string
17-
Config T
18-
}
12+
// Init inits plugin with configuration
13+
Init(config map[string]interface{}) error
1914

20-
func (p *BasePlugin[T]) UnmarshalConfig(data []byte) error {
21-
return json.Unmarshal(data, &p.Config)
22-
}
15+
// GetConfig returns plugin's configuration
16+
GetConfig() map[string]interface{}
2317

24-
func (p *BasePlugin[T]) MarshalConfig() ([]byte, error) {
25-
return json.Marshal(p.Config)
26-
}
18+
// ValidateConfig validates plugin's configuration
19+
ValidateConfig(config map[string]interface{}) error
2720

28-
func (p *BasePlugin[T]) ExecuteOutbound(outbound *Outbound, context *Context) error {
29-
panic("not implemented")
21+
// ExecuteInbound executes inbound
22+
ExecuteInbound(ctx context.Context, inbound *Inbound) (InboundResult, error)
23+
24+
// ExecuteOutbound executes outbound
25+
ExecuteOutbound(ctx context.Context, outbound *Outbound) error
3026
}
3127

32-
func (p *BasePlugin[T]) ExecuteInbound(inbound *Inbound) (InboundResult, error) {
33-
panic("not implemented")
28+
func New(name string) (Plugin, bool) {
29+
r := GetRegistration(name)
30+
if r == nil {
31+
return nil, false
32+
}
33+
return r.Factory(), true
3434
}
3535

3636
type Outbound struct {
@@ -46,10 +46,6 @@ type Inbound struct {
4646
RawBody []byte
4747
}
4848

49-
type Context struct {
50-
//Workspace *entities.Workspace
51-
}
52-
5349
type InboundResult struct {
5450
Terminated bool
5551
Payload []byte

pkg/plugin/registry.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,24 @@ const (
1212
TypeOutbound Type = "outbound"
1313
)
1414

15-
type NewPluginFunc func(config []byte) (Plugin, error)
16-
1715
type Registration struct {
18-
Type Type
19-
New NewPluginFunc
16+
Type Type
17+
Factory func() Plugin
2018
}
2119

2220
var mux sync.RWMutex
23-
var registry = make(map[string]*Registration)
21+
var registry = map[string]*Registration{}
2422

25-
func RegisterPlugin(typ Type, name string, fn NewPluginFunc) {
23+
func RegisterPlugin(typ Type, name string, fn func() Plugin) {
2624
mux.Lock()
2725
defer mux.Unlock()
2826
if _, ok := registry[name]; ok {
2927
panic(fmt.Sprintf("plugin '%s' already registered", name))
3028
}
3129

3230
registry[name] = &Registration{
33-
Type: typ,
34-
New: fn,
31+
Type: typ,
32+
Factory: fn,
3533
}
3634
}
3735

0 commit comments

Comments
 (0)