11import type { EvaluationRequest , EvaluationResponse } from '@openfeature/ofrep-core' ;
2+ import { ErrorMessageMap } from '@openfeature/ofrep-core' ;
23import {
4+ type EvaluationFlagValue ,
5+ handleEvaluationError ,
6+ isEvaluationFailureResponse ,
37 OFREPApi ,
48 OFREPApiFetchError ,
59 OFREPApiTooManyRequestsError ,
610 OFREPApiUnauthorizedError ,
711 OFREPForbiddenError ,
8- isEvaluationFailureResponse ,
9- isEvaluationSuccessResponse ,
12+ toFlagMetadata ,
13+ toResolutionDetails ,
1014} from '@openfeature/ofrep-core' ;
1115import type {
1216 EvaluationContext ,
@@ -30,18 +34,6 @@ import type { EvaluateFlagsResponse } from './model/evaluate-flags-response';
3034import { BulkEvaluationStatus } from './model/evaluate-flags-response' ;
3135import type { FlagCache , MetadataCache } from './model/in-memory-cache' ;
3236import type { OFREPWebProviderOptions } from './model/ofrep-web-provider-options' ;
33- import { isResolutionError } from './model/resolution-error' ;
34-
35- const ErrorMessageMap : { [ key in ErrorCode ] : string } = {
36- [ ErrorCode . FLAG_NOT_FOUND ] : 'Flag was not found' ,
37- [ ErrorCode . GENERAL ] : 'General error' ,
38- [ ErrorCode . INVALID_CONTEXT ] : 'Context is invalid or could be parsed' ,
39- [ ErrorCode . PARSE_ERROR ] : 'Flag or flag configuration could not be parsed' ,
40- [ ErrorCode . PROVIDER_FATAL ] : 'Provider is in a fatal error state' ,
41- [ ErrorCode . PROVIDER_NOT_READY ] : 'Provider is not yet ready' ,
42- [ ErrorCode . TARGETING_KEY_MISSING ] : 'Targeting key is missing' ,
43- [ ErrorCode . TYPE_MISMATCH ] : 'Flag is not of expected type' ,
44- } ;
4537
4638export class OFREPWebProvider implements Provider {
4739 DEFAULT_POLL_INTERVAL = 30000 ;
@@ -62,7 +54,7 @@ export class OFREPWebProvider implements Provider {
6254 private _pollingInterval : number ;
6355 private _retryPollingAfter : Date | undefined ;
6456 private _flagCache : FlagCache = { } ;
65- private _flagSetMetadataCache : MetadataCache = { } ;
57+ private _flagSetMetadataCache ? : MetadataCache = { } ;
6658 private _context : EvaluationContext | undefined ;
6759 private _pollingIntervalId ?: number ;
6860
@@ -109,28 +101,28 @@ export class OFREPWebProvider implements Provider {
109101 defaultValue : boolean ,
110102 context : EvaluationContext ,
111103 ) : ResolutionDetails < boolean > {
112- return this . _resolve ( flagKey , 'boolean' , defaultValue ) ;
104+ return this . _resolve ( flagKey , defaultValue ) ;
113105 }
114106 resolveStringEvaluation (
115107 flagKey : string ,
116108 defaultValue : string ,
117109 context : EvaluationContext ,
118110 ) : ResolutionDetails < string > {
119- return this . _resolve ( flagKey , 'string' , defaultValue ) ;
111+ return this . _resolve ( flagKey , defaultValue ) ;
120112 }
121113 resolveNumberEvaluation (
122114 flagKey : string ,
123115 defaultValue : number ,
124116 context : EvaluationContext ,
125117 ) : ResolutionDetails < number > {
126- return this . _resolve ( flagKey , 'number' , defaultValue ) ;
118+ return this . _resolve ( flagKey , defaultValue ) ;
127119 }
128120 resolveObjectEvaluation < T extends JsonValue > (
129121 flagKey : string ,
130122 defaultValue : T ,
131123 context : EvaluationContext ,
132124 ) : ResolutionDetails < T > {
133- return this . _resolve ( flagKey , 'object' , defaultValue ) ;
125+ return this . _resolve ( flagKey , defaultValue ) ;
134126 }
135127
136128 /**
@@ -204,36 +196,24 @@ export class OFREPWebProvider implements Provider {
204196 }
205197
206198 const bulkSuccessResp = response . value ;
207- const newCache : FlagCache = { } ;
208-
209- if ( 'flags' in bulkSuccessResp && Array . isArray ( bulkSuccessResp . flags ) ) {
210- bulkSuccessResp . flags . forEach ( ( evalResp : EvaluationResponse ) => {
211- if ( isEvaluationFailureResponse ( evalResp ) ) {
212- newCache [ evalResp . key ] = {
213- reason : StandardResolutionReasons . ERROR ,
214- flagMetadata : evalResp . metadata ,
215- errorCode : evalResp . errorCode ,
216- errorDetails : evalResp . errorDetails ,
217- } ;
218- }
219-
220- if ( isEvaluationSuccessResponse ( evalResp ) && evalResp . key ) {
221- newCache [ evalResp . key ] = {
222- value : evalResp . value ,
223- variant : evalResp . variant ,
224- reason : evalResp . reason ,
225- flagMetadata : evalResp . metadata ,
226- } ;
227- }
228- } ) ;
229- const listUpdatedFlags = this . _getListUpdatedFlags ( this . _flagCache , newCache ) ;
230- this . _flagCache = newCache ;
231- this . _etag = response . httpResponse ?. headers . get ( 'etag' ) ;
232- this . _flagSetMetadataCache = typeof bulkSuccessResp . metadata === 'object' ? bulkSuccessResp . metadata : { } ;
233- return { status : BulkEvaluationStatus . SUCCESS_WITH_CHANGES , flags : listUpdatedFlags } ;
234- } else {
199+ if ( ! ( 'flags' in bulkSuccessResp ) || ! Array . isArray ( bulkSuccessResp . flags ) ) {
235200 throw new Error ( 'No flags in OFREP bulk evaluation response' ) ;
236201 }
202+
203+ const newCache = bulkSuccessResp . flags . reduce < FlagCache > ( ( currentCache , currentResponse ) => {
204+ if ( currentResponse . key ) {
205+ currentCache [ currentResponse . key ] = currentResponse ;
206+ }
207+ return currentCache ;
208+ } , { } ) ;
209+
210+ const listUpdatedFlags = this . _getListUpdatedFlags ( this . _flagCache , newCache ) ;
211+ this . _flagCache = newCache ;
212+ this . _etag = response . httpResponse ?. headers . get ( 'etag' ) ;
213+ this . _flagSetMetadataCache = toFlagMetadata (
214+ typeof bulkSuccessResp . metadata === 'object' ? bulkSuccessResp . metadata : { } ,
215+ ) ;
216+ return { status : BulkEvaluationStatus . SUCCESS_WITH_CHANGES , flags : listUpdatedFlags } ;
237217 } catch ( error ) {
238218 if ( error instanceof OFREPApiTooManyRequestsError && error . retryAfterDate !== null ) {
239219 this . _retryPollingAfter = error . retryAfterDate ;
@@ -278,7 +258,7 @@ export class OFREPWebProvider implements Provider {
278258 * @param defaultValue - default value
279259 * @private
280260 */
281- private _resolve < T extends FlagValue > ( flagKey : string , type : string , defaultValue : T ) : ResolutionDetails < T > {
261+ private _resolve < T extends FlagValue > ( flagKey : string , defaultValue : T ) : ResolutionDetails < T > {
282262 const resolved = this . _flagCache [ flagKey ] ;
283263
284264 if ( ! resolved ) {
@@ -291,32 +271,18 @@ export class OFREPWebProvider implements Provider {
291271 } ;
292272 }
293273
294- if ( isResolutionError ( resolved ) ) {
295- return {
296- ...resolved ,
297- value : defaultValue ,
298- errorMessage : ErrorMessageMap [ resolved . errorCode ] ,
299- } ;
300- }
274+ return this . responseToResolutionDetails ( resolved , defaultValue ) ;
275+ }
301276
302- if ( typeof resolved . value !== type ) {
303- return {
304- value : defaultValue ,
305- flagMetadata : resolved . flagMetadata ,
306- reason : StandardResolutionReasons . ERROR ,
307- errorCode : ErrorCode . TYPE_MISMATCH ,
308- errorMessage : ErrorMessageMap [ ErrorCode . TYPE_MISMATCH ] ,
309- } ;
277+ private responseToResolutionDetails < T extends EvaluationFlagValue > (
278+ response : EvaluationResponse ,
279+ defaultValue : T ,
280+ ) : ResolutionDetails < T > {
281+ if ( isEvaluationFailureResponse ( response ) ) {
282+ return handleEvaluationError ( response , defaultValue ) ;
310283 }
311284
312- return {
313- variant : resolved . variant ,
314- value : resolved . value as T ,
315- flagMetadata : resolved . flagMetadata ,
316- errorCode : resolved . errorCode ,
317- errorMessage : resolved . errorMessage ,
318- reason : resolved . reason ,
319- } ;
285+ return toResolutionDetails ( response , defaultValue ) ;
320286 }
321287
322288 /**
0 commit comments