@@ -5,14 +5,16 @@ import (
55 "fmt"
66 "io"
77 "net/url"
8+ "os"
89 "reflect"
9- "strings "
10+ "strconv "
1011 "time"
1112
1213 // Packages
13- "github.com/mutablelogic/go-server"
14+ server "github.com/mutablelogic/go-server"
1415 httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
1516 ast "github.com/mutablelogic/go-server/pkg/parser/ast"
17+ types "github.com/mutablelogic/go-server/pkg/types"
1618)
1719
1820////////////////////////////////////////////////////////////////////////////////
@@ -21,7 +23,9 @@ import (
2123type Meta struct {
2224 Name string
2325 Description string
26+ Default string
2427 Type reflect.Type
28+ Index []int
2529 Fields []* Meta
2630}
2731
@@ -93,6 +97,9 @@ func (m *Meta) Write(w io.Writer) error {
9397 buf .WriteString (" // " )
9498 buf .WriteString (field .Description )
9599 }
100+ if field .Default != "" {
101+ buf .WriteString (" (default: " + types .Quote (field .Default ) + ")" )
102+ }
96103
97104 buf .WriteString ("\n " )
98105 }
@@ -114,16 +121,20 @@ func (m *Meta) Validate(values any) error {
114121}
115122
116123func (m * Meta ) New () server.Plugin {
117- return reflect .New (m .Type ).Interface ().(server.Plugin )
124+ obj := reflect .New (m .Type )
125+ for _ , field := range m .Fields {
126+ // Expand field for env
127+ setValue (obj .Elem ().FieldByIndex (field .Index ), os .ExpandEnv (field .Default ))
128+ }
129+ return obj .Interface ().(server.Plugin )
118130}
119131
120132////////////////////////////////////////////////////////////////////////////////
121133// PRIVATE METHODS
122134
123135func newMetaField (rf reflect.StructField ) (* Meta , error ) {
124136 meta := new (Meta )
125-
126- //fmt.Println("newMetaField", rf.Name, rf.Type)
137+ meta .Index = rf .Index
127138
128139 // Name
129140 if name := nameForField (rf , "json" , "yaml" , "name" ); name == "" {
@@ -134,7 +145,16 @@ func newMetaField(rf reflect.StructField) (*Meta, error) {
134145 }
135146
136147 // Description
137- meta .Description = rf .Tag .Get ("help" )
148+ if description , _ := valueForField (rf , "description" , "help" ); description != "" {
149+ meta .Description = description
150+ }
151+
152+ // Env - needs to be an identififer
153+ if env , _ := valueForField (rf , "env" ); types .IsIdentifier (env ) {
154+ meta .Default = "${" + env + "}"
155+ } else if def , _ := valueForField (rf , "default" ); def != "" {
156+ meta .Default = def
157+ }
138158
139159 // Type
140160 if t := typeName (rf .Type ); t == "" {
@@ -152,6 +172,67 @@ var (
152172 durationType = reflect .TypeOf (time .Duration (0 ))
153173)
154174
175+ func setValue (rv reflect.Value , str string ) error {
176+ switch rv .Kind () {
177+ case reflect .Bool :
178+ // Zero value
179+ if str == "" {
180+ rv .SetZero ()
181+ }
182+ // Bool
183+ if v , err := strconv .ParseBool (str ); err != nil {
184+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
185+ } else {
186+ rv .SetBool (v )
187+ }
188+ case reflect .Int , reflect .Int8 , reflect .Int16 , reflect .Int32 , reflect .Int64 :
189+ // Zero value
190+ if str == "" {
191+ rv .SetZero ()
192+ }
193+ // Duration
194+ if rv .Type () == durationType {
195+ if v , err := time .ParseDuration (str ); err != nil {
196+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
197+ } else {
198+ rv .Set (reflect .ValueOf (v ))
199+ }
200+ }
201+ // Int
202+ if v , err := strconv .ParseInt (str , 10 , 64 ); err != nil {
203+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
204+ } else {
205+ rv .SetInt (v )
206+ }
207+ case reflect .Uint , reflect .Uint8 , reflect .Uint16 , reflect .Uint32 , reflect .Uint64 :
208+ // Zero value
209+ if str == "" {
210+ rv .SetZero ()
211+ }
212+ // Uint
213+ if v , err := strconv .ParseUint (str , 10 , 64 ); err != nil {
214+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
215+ } else {
216+ rv .SetUint (v )
217+ }
218+ case reflect .Float32 , reflect .Float64 :
219+ // Zero value
220+ if str == "" {
221+ rv .SetZero ()
222+ }
223+ // Float
224+ if v , err := strconv .ParseFloat (str , 64 ); err != nil {
225+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
226+ } else {
227+ rv .SetFloat (v )
228+ }
229+ case reflect .String :
230+ // String
231+ rv .SetString (str )
232+ }
233+ return httpresponse .ErrBadRequest .Withf ("invalid value for %s: %q" , rv .Type (), str )
234+ }
235+
155236func typeName (rt reflect.Type ) string {
156237 if rt .Kind () == reflect .Ptr {
157238 rt = rt .Elem ()
@@ -189,20 +270,26 @@ func typeName(rt reflect.Type) string {
189270 return "ref"
190271}
191272
192- func nameForField ( rt reflect.StructField , tags ... string ) string {
273+ func valueForField ( rf reflect.StructField , tags ... string ) ( string , bool ) {
193274 for _ , tag := range tags {
194- tag , ok := rt .Tag .Lookup (tag )
275+ tag , ok := rf .Tag .Lookup (tag )
195276 if ! ok {
196277 continue
197278 }
198- if tag == "-" || tag == "" {
279+ if tag == "-" {
199280 // Ignore
200- return ""
201- }
202- name := strings .Split (tag , "," )
203- if len (name ) > 0 && name [0 ] != "" {
204- return name [0 ]
281+ return "" , true
282+ } else {
283+ return tag , true
205284 }
206285 }
286+ return "" , false
287+ }
288+
289+ func nameForField (rt reflect.StructField , tags ... string ) string {
290+ value , exists := valueForField (rt , tags ... )
291+ if exists {
292+ return value
293+ }
207294 return rt .Name
208295}
0 commit comments