@@ -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