@@ -19,11 +19,11 @@ type IClient interface {
1919 FloatValue (ctx context.Context , flag string , defaultValue float64 , evalCtx EvaluationContext , options ... Option ) (float64 , error )
2020 IntValue (ctx context.Context , flag string , defaultValue int64 , evalCtx EvaluationContext , options ... Option ) (int64 , error )
2121 ObjectValue (ctx context.Context , flag string , defaultValue interface {}, evalCtx EvaluationContext , options ... Option ) (interface {}, error )
22- BooleanValueDetails (ctx context.Context , flag string , defaultValue bool , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error )
23- StringValueDetails (ctx context.Context , flag string , defaultValue string , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error )
24- FloatValueDetails (ctx context.Context , flag string , defaultValue float64 , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error )
25- IntValueDetails (ctx context.Context , flag string , defaultValue int64 , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error )
26- ObjectValueDetails (ctx context.Context , flag string , defaultValue interface {}, evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error )
22+ BooleanValueDetails (ctx context.Context , flag string , defaultValue bool , evalCtx EvaluationContext , options ... Option ) (BooleanEvaluationDetails , error )
23+ StringValueDetails (ctx context.Context , flag string , defaultValue string , evalCtx EvaluationContext , options ... Option ) (StringEvaluationDetails , error )
24+ FloatValueDetails (ctx context.Context , flag string , defaultValue float64 , evalCtx EvaluationContext , options ... Option ) (FloatEvaluationDetails , error )
25+ IntValueDetails (ctx context.Context , flag string , defaultValue int64 , evalCtx EvaluationContext , options ... Option ) (IntEvaluationDetails , error )
26+ ObjectValueDetails (ctx context.Context , flag string , defaultValue interface {}, evalCtx EvaluationContext , options ... Option ) (InterfaceEvaluationDetails , error )
2727}
2828
2929// ClientMetadata provides a client's metadata
@@ -110,10 +110,34 @@ var typeToString = map[Type]string{
110110type EvaluationDetails struct {
111111 FlagKey string
112112 FlagType Type
113- Value interface {}
114113 ResolutionDetail
115114}
116115
116+ type BooleanEvaluationDetails struct {
117+ Value bool
118+ EvaluationDetails
119+ }
120+
121+ type StringEvaluationDetails struct {
122+ Value string
123+ EvaluationDetails
124+ }
125+
126+ type FloatEvaluationDetails struct {
127+ Value float64
128+ EvaluationDetails
129+ }
130+
131+ type IntEvaluationDetails struct {
132+ Value int64
133+ EvaluationDetails
134+ }
135+
136+ type InterfaceEvaluationDetails struct {
137+ Value interface {}
138+ EvaluationDetails
139+ }
140+
117141type ResolutionDetail struct {
118142 Variant string
119143 Reason Reason
@@ -292,13 +316,41 @@ func (c Client) ObjectValue(ctx context.Context, flag string, defaultValue inter
292316// - defaultValue is returned if an error occurs
293317// - evalCtx is the evaluation context used in a flag evaluation (not to be confused with ctx)
294318// - options are optional additional evaluation options e.g. WithHooks & WithHookHints
295- func (c Client ) BooleanValueDetails (ctx context.Context , flag string , defaultValue bool , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error ) {
319+ func (c Client ) BooleanValueDetails (ctx context.Context , flag string , defaultValue bool , evalCtx EvaluationContext , options ... Option ) (BooleanEvaluationDetails , error ) {
296320 evalOptions := & EvaluationOptions {}
297321 for _ , option := range options {
298322 option (evalOptions )
299323 }
300324
301- return c .evaluate (ctx , flag , Boolean , defaultValue , evalCtx , * evalOptions )
325+ evalDetails , err := c .evaluate (ctx , flag , Boolean , defaultValue , evalCtx , * evalOptions )
326+ if err != nil {
327+ return BooleanEvaluationDetails {
328+ Value : defaultValue ,
329+ EvaluationDetails : evalDetails .EvaluationDetails ,
330+ }, err
331+ }
332+
333+ value , ok := evalDetails .Value .(bool )
334+ if ! ok {
335+ err := errors .New ("evaluated value is not a boolean" )
336+ c .logger ().Error (
337+ err , "invalid flag resolution type" , "expectedType" , "boolean" ,
338+ "gotType" , fmt .Sprintf ("%T" , evalDetails .Value ),
339+ )
340+ boolEvalDetails := BooleanEvaluationDetails {
341+ Value : defaultValue ,
342+ EvaluationDetails : evalDetails .EvaluationDetails ,
343+ }
344+ boolEvalDetails .EvaluationDetails .ErrorCode = TypeMismatchCode
345+ boolEvalDetails .EvaluationDetails .ErrorMessage = err .Error ()
346+
347+ return boolEvalDetails , err
348+ }
349+
350+ return BooleanEvaluationDetails {
351+ Value : value ,
352+ EvaluationDetails : evalDetails .EvaluationDetails ,
353+ }, nil
302354}
303355
304356// StringValueDetails performs a flag evaluation that returns an evaluation details struct.
@@ -309,13 +361,41 @@ func (c Client) BooleanValueDetails(ctx context.Context, flag string, defaultVal
309361// - defaultValue is returned if an error occurs
310362// - evalCtx is the evaluation context used in a flag evaluation (not to be confused with ctx)
311363// - options are optional additional evaluation options e.g. WithHooks & WithHookHints
312- func (c Client ) StringValueDetails (ctx context.Context , flag string , defaultValue string , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error ) {
364+ func (c Client ) StringValueDetails (ctx context.Context , flag string , defaultValue string , evalCtx EvaluationContext , options ... Option ) (StringEvaluationDetails , error ) {
313365 evalOptions := & EvaluationOptions {}
314366 for _ , option := range options {
315367 option (evalOptions )
316368 }
317369
318- return c .evaluate (ctx , flag , String , defaultValue , evalCtx , * evalOptions )
370+ evalDetails , err := c .evaluate (ctx , flag , String , defaultValue , evalCtx , * evalOptions )
371+ if err != nil {
372+ return StringEvaluationDetails {
373+ Value : defaultValue ,
374+ EvaluationDetails : evalDetails .EvaluationDetails ,
375+ }, err
376+ }
377+
378+ value , ok := evalDetails .Value .(string )
379+ if ! ok {
380+ err := errors .New ("evaluated value is not a string" )
381+ c .logger ().Error (
382+ err , "invalid flag resolution type" , "expectedType" , "string" ,
383+ "gotType" , fmt .Sprintf ("%T" , evalDetails .Value ),
384+ )
385+ strEvalDetails := StringEvaluationDetails {
386+ Value : defaultValue ,
387+ EvaluationDetails : evalDetails .EvaluationDetails ,
388+ }
389+ strEvalDetails .EvaluationDetails .ErrorCode = TypeMismatchCode
390+ strEvalDetails .EvaluationDetails .ErrorMessage = err .Error ()
391+
392+ return strEvalDetails , err
393+ }
394+
395+ return StringEvaluationDetails {
396+ Value : value ,
397+ EvaluationDetails : evalDetails .EvaluationDetails ,
398+ }, nil
319399}
320400
321401// FloatValueDetails performs a flag evaluation that returns an evaluation details struct.
@@ -326,13 +406,41 @@ func (c Client) StringValueDetails(ctx context.Context, flag string, defaultValu
326406// - defaultValue is returned if an error occurs
327407// - evalCtx is the evaluation context used in a flag evaluation (not to be confused with ctx)
328408// - options are optional additional evaluation options e.g. WithHooks & WithHookHints
329- func (c Client ) FloatValueDetails (ctx context.Context , flag string , defaultValue float64 , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error ) {
409+ func (c Client ) FloatValueDetails (ctx context.Context , flag string , defaultValue float64 , evalCtx EvaluationContext , options ... Option ) (FloatEvaluationDetails , error ) {
330410 evalOptions := & EvaluationOptions {}
331411 for _ , option := range options {
332412 option (evalOptions )
333413 }
334414
335- return c .evaluate (ctx , flag , Float , defaultValue , evalCtx , * evalOptions )
415+ evalDetails , err := c .evaluate (ctx , flag , Float , defaultValue , evalCtx , * evalOptions )
416+ if err != nil {
417+ return FloatEvaluationDetails {
418+ Value : defaultValue ,
419+ EvaluationDetails : evalDetails .EvaluationDetails ,
420+ }, err
421+ }
422+
423+ value , ok := evalDetails .Value .(float64 )
424+ if ! ok {
425+ err := errors .New ("evaluated value is not a float64" )
426+ c .logger ().Error (
427+ err , "invalid flag resolution type" , "expectedType" , "float64" ,
428+ "gotType" , fmt .Sprintf ("%T" , evalDetails .Value ),
429+ )
430+ floatEvalDetails := FloatEvaluationDetails {
431+ Value : defaultValue ,
432+ EvaluationDetails : evalDetails .EvaluationDetails ,
433+ }
434+ floatEvalDetails .EvaluationDetails .ErrorCode = TypeMismatchCode
435+ floatEvalDetails .EvaluationDetails .ErrorMessage = err .Error ()
436+
437+ return floatEvalDetails , err
438+ }
439+
440+ return FloatEvaluationDetails {
441+ Value : value ,
442+ EvaluationDetails : evalDetails .EvaluationDetails ,
443+ }, nil
336444}
337445
338446// IntValueDetails performs a flag evaluation that returns an evaluation details struct.
@@ -343,13 +451,41 @@ func (c Client) FloatValueDetails(ctx context.Context, flag string, defaultValue
343451// - defaultValue is returned if an error occurs
344452// - evalCtx is the evaluation context used in a flag evaluation (not to be confused with ctx)
345453// - options are optional additional evaluation options e.g. WithHooks & WithHookHints
346- func (c Client ) IntValueDetails (ctx context.Context , flag string , defaultValue int64 , evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error ) {
454+ func (c Client ) IntValueDetails (ctx context.Context , flag string , defaultValue int64 , evalCtx EvaluationContext , options ... Option ) (IntEvaluationDetails , error ) {
347455 evalOptions := & EvaluationOptions {}
348456 for _ , option := range options {
349457 option (evalOptions )
350458 }
351459
352- return c .evaluate (ctx , flag , Int , defaultValue , evalCtx , * evalOptions )
460+ evalDetails , err := c .evaluate (ctx , flag , Int , defaultValue , evalCtx , * evalOptions )
461+ if err != nil {
462+ return IntEvaluationDetails {
463+ Value : defaultValue ,
464+ EvaluationDetails : evalDetails .EvaluationDetails ,
465+ }, err
466+ }
467+
468+ value , ok := evalDetails .Value .(int64 )
469+ if ! ok {
470+ err := errors .New ("evaluated value is not an int64" )
471+ c .logger ().Error (
472+ err , "invalid flag resolution type" , "expectedType" , "int64" ,
473+ "gotType" , fmt .Sprintf ("%T" , evalDetails .Value ),
474+ )
475+ intEvalDetails := IntEvaluationDetails {
476+ Value : defaultValue ,
477+ EvaluationDetails : evalDetails .EvaluationDetails ,
478+ }
479+ intEvalDetails .EvaluationDetails .ErrorCode = TypeMismatchCode
480+ intEvalDetails .EvaluationDetails .ErrorMessage = err .Error ()
481+
482+ return intEvalDetails , err
483+ }
484+
485+ return IntEvaluationDetails {
486+ Value : value ,
487+ EvaluationDetails : evalDetails .EvaluationDetails ,
488+ }, nil
353489}
354490
355491// ObjectValueDetails performs a flag evaluation that returns an evaluation details struct.
@@ -360,7 +496,7 @@ func (c Client) IntValueDetails(ctx context.Context, flag string, defaultValue i
360496// - defaultValue is returned if an error occurs
361497// - evalCtx is the evaluation context used in a flag evaluation (not to be confused with ctx)
362498// - options are optional additional evaluation options e.g. WithHooks & WithHookHints
363- func (c Client ) ObjectValueDetails (ctx context.Context , flag string , defaultValue interface {}, evalCtx EvaluationContext , options ... Option ) (EvaluationDetails , error ) {
499+ func (c Client ) ObjectValueDetails (ctx context.Context , flag string , defaultValue interface {}, evalCtx EvaluationContext , options ... Option ) (InterfaceEvaluationDetails , error ) {
364500 evalOptions := & EvaluationOptions {}
365501 for _ , option := range options {
366502 option (evalOptions )
@@ -371,7 +507,7 @@ func (c Client) ObjectValueDetails(ctx context.Context, flag string, defaultValu
371507
372508func (c Client ) evaluate (
373509 ctx context.Context , flag string , flagType Type , defaultValue interface {}, evalCtx EvaluationContext , options EvaluationOptions ,
374- ) (EvaluationDetails , error ) {
510+ ) (InterfaceEvaluationDetails , error ) {
375511 c .logger ().V (debug ).Info (
376512 "evaluating flag" , "flag" , flag , "type" , flagType .String (), "defaultValue" , defaultValue ,
377513 "evaluationContext" , evalCtx , "evaluationOptions" , options ,
@@ -387,10 +523,12 @@ func (c Client) evaluate(
387523 providerMetadata : api .provider .Metadata (),
388524 evaluationContext : evalCtx ,
389525 }
390- evalDetails := EvaluationDetails {
391- FlagKey : flag ,
392- FlagType : flagType ,
393- Value : defaultValue ,
526+ evalDetails := InterfaceEvaluationDetails {
527+ Value : defaultValue ,
528+ EvaluationDetails : EvaluationDetails {
529+ FlagKey : flag ,
530+ FlagType : flagType ,
531+ },
394532 }
395533
396534 apiClientInvocationProviderHooks := append (append (append (api .hooks , c .hooks ... ), options .hooks ... ), api .provider .Hooks ()... ) // API, Client, Invocation, Provider
@@ -500,7 +638,7 @@ func (c Client) beforeHooks(
500638}
501639
502640func (c Client ) afterHooks (
503- hookCtx HookContext , hooks []Hook , evalDetails EvaluationDetails , options EvaluationOptions ,
641+ hookCtx HookContext , hooks []Hook , evalDetails InterfaceEvaluationDetails , options EvaluationOptions ,
504642) error {
505643 c .logger ().V (debug ).Info ("executing after hooks" )
506644 defer c .logger ().V (debug ).Info ("executed after hooks" )
0 commit comments