@@ -7,7 +7,7 @@ import type {
7
7
EvaluationContext ,
8
8
ResolutionReason ,
9
9
} from '@openfeature/core' ;
10
- import { ParseError , StandardResolutionReasons , ErrorCode } from '@openfeature/core' ;
10
+ import { StandardResolutionReasons , ErrorCode , GeneralError } from '@openfeature/core' ;
11
11
import { sha1 } from 'object-hash' ;
12
12
import { Targeting } from './targeting/targeting' ;
13
13
@@ -45,7 +45,7 @@ type RequiredResolutionDetails<T> = Omit<ResolutionDetails<T>, 'value'> & {
45
45
export class FeatureFlag {
46
46
private readonly _key : string ;
47
47
private readonly _state : 'ENABLED' | 'DISABLED' ;
48
- private readonly _defaultVariant : string ;
48
+ private readonly _defaultVariant : string | undefined ;
49
49
private readonly _variants : Map < string , FlagValue > ;
50
50
private readonly _hash : string ;
51
51
private readonly _metadata : FlagMetadata ;
@@ -59,7 +59,7 @@ export class FeatureFlag {
59
59
) {
60
60
this . _key = key ;
61
61
this . _state = flag [ 'state' ] ;
62
- this . _defaultVariant = flag [ 'defaultVariant' ] ;
62
+ this . _defaultVariant = flag [ 'defaultVariant' ] || undefined ;
63
63
this . _variants = new Map < string , FlagValue > ( Object . entries ( flag [ 'variants' ] ) ) ;
64
64
this . _metadata = flag [ 'metadata' ] ?? { } ;
65
65
@@ -89,7 +89,7 @@ export class FeatureFlag {
89
89
return this . _state ;
90
90
}
91
91
92
- get defaultVariant ( ) : string {
92
+ get defaultVariant ( ) : string | undefined {
93
93
return this . _defaultVariant ;
94
94
}
95
95
@@ -102,7 +102,7 @@ export class FeatureFlag {
102
102
}
103
103
104
104
evaluate ( evalCtx : EvaluationContext , logger : Logger = this . logger ) : RequiredResolutionDetails < JsonValue > {
105
- let variant : string ;
105
+ let variant : string | undefined ;
106
106
let reason : ResolutionReason ;
107
107
108
108
if ( this . _targetingParseErrorMessage ) {
@@ -142,7 +142,21 @@ export class FeatureFlag {
142
142
}
143
143
}
144
144
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 ) ;
146
160
if ( resolvedValue === undefined ) {
147
161
return {
148
162
reason : StandardResolutionReasons . ERROR ,
@@ -155,7 +169,7 @@ export class FeatureFlag {
155
169
return {
156
170
value : resolvedValue ,
157
171
reason,
158
- variant,
172
+ variant : resolvedVariant ,
159
173
flagMetadata : this . metadata ,
160
174
} ;
161
175
}
@@ -164,14 +178,10 @@ export class FeatureFlag {
164
178
// basic validation, ideally this sort of thing is caught by IDEs and other schema validation before we get here
165
179
// consistent with Java/Go and other implementations, we only warn for schema validation, but we fail for this sort of basic structural errors
166
180
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 ) } ` ) ;
172
182
}
173
- if ( ! this . _variants . has ( this . _defaultVariant ) ) {
174
- throw new ParseError (
183
+ if ( this . _defaultVariant && ! this . _variants . has ( this . _defaultVariant ) ) {
184
+ throw new GeneralError (
175
185
`Default variant ${ this . _defaultVariant } missing from variants ${ JSON . stringify ( this . _variants , undefined , 2 ) } ` ,
176
186
) ;
177
187
}
0 commit comments