@@ -7,7 +7,7 @@ import type {
77 EvaluationContext ,
88 ResolutionReason ,
99} from '@openfeature/core' ;
10- import { ParseError , StandardResolutionReasons , ErrorCode } from '@openfeature/core' ;
10+ import { StandardResolutionReasons , ErrorCode , GeneralError } from '@openfeature/core' ;
1111import { sha1 } from 'object-hash' ;
1212import { Targeting } from './targeting/targeting' ;
1313
@@ -45,7 +45,7 @@ type RequiredResolutionDetails<T> = Omit<ResolutionDetails<T>, 'value'> & {
4545export class FeatureFlag {
4646 private readonly _key : string ;
4747 private readonly _state : 'ENABLED' | 'DISABLED' ;
48- private readonly _defaultVariant : string ;
48+ private readonly _defaultVariant : string | undefined ;
4949 private readonly _variants : Map < string , FlagValue > ;
5050 private readonly _hash : string ;
5151 private readonly _metadata : FlagMetadata ;
@@ -59,7 +59,7 @@ export class FeatureFlag {
5959 ) {
6060 this . _key = key ;
6161 this . _state = flag [ 'state' ] ;
62- this . _defaultVariant = flag [ 'defaultVariant' ] ;
62+ this . _defaultVariant = flag [ 'defaultVariant' ] || undefined ;
6363 this . _variants = new Map < string , FlagValue > ( Object . entries ( flag [ 'variants' ] ) ) ;
6464 this . _metadata = flag [ 'metadata' ] ?? { } ;
6565
@@ -89,7 +89,7 @@ export class FeatureFlag {
8989 return this . _state ;
9090 }
9191
92- get defaultVariant ( ) : string {
92+ get defaultVariant ( ) : string | undefined {
9393 return this . _defaultVariant ;
9494 }
9595
@@ -102,7 +102,7 @@ export class FeatureFlag {
102102 }
103103
104104 evaluate ( evalCtx : EvaluationContext , logger : Logger = this . logger ) : RequiredResolutionDetails < JsonValue > {
105- let variant : string ;
105+ let variant : string | undefined ;
106106 let reason : ResolutionReason ;
107107
108108 if ( this . _targetingParseErrorMessage ) {
@@ -142,7 +142,21 @@ export class FeatureFlag {
142142 }
143143 }
144144
145- const resolvedValue = this . _variants . get ( variant ) ;
145+ if (
146+ ( variant === undefined || variant === null ) &&
147+ ( this . defaultVariant === null || this . defaultVariant === undefined )
148+ ) {
149+ return {
150+ reason : StandardResolutionReasons . ERROR ,
151+ errorCode : ErrorCode . FLAG_NOT_FOUND ,
152+ errorMessage : `Flag '${ this . _key } ' has no default variant defined, will use code default` ,
153+ flagMetadata : this . metadata ,
154+ } ;
155+ }
156+
157+ const resolvedVariant = variant as string ;
158+
159+ const resolvedValue = this . _variants . get ( resolvedVariant ) ;
146160 if ( resolvedValue === undefined ) {
147161 return {
148162 reason : StandardResolutionReasons . ERROR ,
@@ -155,7 +169,7 @@ export class FeatureFlag {
155169 return {
156170 value : resolvedValue ,
157171 reason,
158- variant,
172+ variant : resolvedVariant ,
159173 flagMetadata : this . metadata ,
160174 } ;
161175 }
@@ -164,14 +178,10 @@ export class FeatureFlag {
164178 // basic validation, ideally this sort of thing is caught by IDEs and other schema validation before we get here
165179 // consistent with Java/Go and other implementations, we only warn for schema validation, but we fail for this sort of basic structural errors
166180 if ( this . _state !== 'ENABLED' && this . _state !== 'DISABLED' ) {
167- throw new ParseError ( `Invalid flag state: ${ JSON . stringify ( this . _state , undefined , 2 ) } ` ) ;
168- }
169- if ( this . _defaultVariant === undefined ) {
170- // this can be falsy, and int, etc...
171- throw new ParseError ( `Invalid flag defaultVariant: ${ JSON . stringify ( this . _defaultVariant , undefined , 2 ) } ` ) ;
181+ throw new GeneralError ( `Invalid flag state: ${ JSON . stringify ( this . _state , undefined , 2 ) } ` ) ;
172182 }
173- if ( ! this . _variants . has ( this . _defaultVariant ) ) {
174- throw new ParseError (
183+ if ( this . _defaultVariant && ! this . _variants . has ( this . _defaultVariant ) ) {
184+ throw new GeneralError (
175185 `Default variant ${ this . _defaultVariant } missing from variants ${ JSON . stringify ( this . _variants , undefined , 2 ) } ` ,
176186 ) ;
177187 }
0 commit comments