@openfeature/ofrep-web-provider 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -187,7 +187,7 @@
187
187
  same "printed page" as the copyright notice for easier
188
188
  identification within third-party archives.
189
189
 
190
- Copyright [yyyy] [name of copyright owner]
190
+ Copyright OpenFeature Maintainers
191
191
 
192
192
  Licensed under the Apache License, Version 2.0 (the "License");
193
193
  you may not use this file except in compliance with the License.
package/index.cjs.js CHANGED
@@ -41,23 +41,6 @@ var BulkEvaluationStatus;
41
41
  BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
42
42
  })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
43
43
 
44
- function isResolutionError(response) {
45
- if (!response || typeof response !== 'object') {
46
- return false;
47
- }
48
- return 'reason' in response && 'errorCode' in response && !('value' in response);
49
- }
50
-
51
- const ErrorMessageMap = {
52
- [webSdk.ErrorCode.FLAG_NOT_FOUND]: 'Flag was not found',
53
- [webSdk.ErrorCode.GENERAL]: 'General error',
54
- [webSdk.ErrorCode.INVALID_CONTEXT]: 'Context is invalid or could be parsed',
55
- [webSdk.ErrorCode.PARSE_ERROR]: 'Flag or flag configuration could not be parsed',
56
- [webSdk.ErrorCode.PROVIDER_FATAL]: 'Provider is in a fatal error state',
57
- [webSdk.ErrorCode.PROVIDER_NOT_READY]: 'Provider is not yet ready',
58
- [webSdk.ErrorCode.TARGETING_KEY_MISSING]: 'Targeting key is missing',
59
- [webSdk.ErrorCode.TYPE_MISMATCH]: 'Flag is not of expected type',
60
- };
61
44
  class OFREPWebProvider {
62
45
  constructor(options, logger) {
63
46
  var _a;
@@ -68,7 +51,6 @@ class OFREPWebProvider {
68
51
  this.runsOn = 'client';
69
52
  this.events = new webSdk.OpenFeatureEventEmitter();
70
53
  this._flagCache = {};
71
- this._flagSetMetadataCache = {};
72
54
  this._options = options;
73
55
  this._logger = logger;
74
56
  this._etag = null;
@@ -107,16 +89,16 @@ class OFREPWebProvider {
107
89
  /* eslint-disable @typescript-eslint/no-unused-vars*/
108
90
  /* to make overrides easier we keep these unused vars */
109
91
  resolveBooleanEvaluation(flagKey, defaultValue, context) {
110
- return this._resolve(flagKey, 'boolean', defaultValue);
92
+ return this._resolve(flagKey, defaultValue);
111
93
  }
112
94
  resolveStringEvaluation(flagKey, defaultValue, context) {
113
- return this._resolve(flagKey, 'string', defaultValue);
95
+ return this._resolve(flagKey, defaultValue);
114
96
  }
115
97
  resolveNumberEvaluation(flagKey, defaultValue, context) {
116
- return this._resolve(flagKey, 'number', defaultValue);
98
+ return this._resolve(flagKey, defaultValue);
117
99
  }
118
100
  resolveObjectEvaluation(flagKey, defaultValue, context) {
119
- return this._resolve(flagKey, 'object', defaultValue);
101
+ return this._resolve(flagKey, defaultValue);
120
102
  }
121
103
  /**
122
104
  * onContextChange is called when the context changes, it will re-evaluate the flags with the new context
@@ -185,35 +167,20 @@ class OFREPWebProvider {
185
167
  throw new webSdk.GeneralError(`Failed OFREP bulk evaluation request, status: ${response.httpStatus}`);
186
168
  }
187
169
  const bulkSuccessResp = response.value;
188
- const newCache = {};
189
- if ('flags' in bulkSuccessResp && Array.isArray(bulkSuccessResp.flags)) {
190
- bulkSuccessResp.flags.forEach((evalResp) => {
191
- if (ofrepCore.isEvaluationFailureResponse(evalResp)) {
192
- newCache[evalResp.key] = {
193
- reason: webSdk.StandardResolutionReasons.ERROR,
194
- flagMetadata: evalResp.metadata,
195
- errorCode: evalResp.errorCode,
196
- errorDetails: evalResp.errorDetails,
197
- };
198
- }
199
- if (ofrepCore.isEvaluationSuccessResponse(evalResp) && evalResp.key) {
200
- newCache[evalResp.key] = {
201
- value: evalResp.value,
202
- variant: evalResp.variant,
203
- reason: evalResp.reason,
204
- flagMetadata: evalResp.metadata,
205
- };
206
- }
207
- });
208
- const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
209
- this._flagCache = newCache;
210
- this._etag = (_a = response.httpResponse) === null || _a === void 0 ? void 0 : _a.headers.get('etag');
211
- this._flagSetMetadataCache = typeof bulkSuccessResp.metadata === 'object' ? bulkSuccessResp.metadata : {};
212
- return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
213
- }
214
- else {
170
+ if (!('flags' in bulkSuccessResp) || !Array.isArray(bulkSuccessResp.flags)) {
215
171
  throw new Error('No flags in OFREP bulk evaluation response');
216
172
  }
173
+ const newCache = bulkSuccessResp.flags.reduce((currentCache, currentResponse) => {
174
+ if (currentResponse.key) {
175
+ currentCache[currentResponse.key] = currentResponse;
176
+ }
177
+ return currentCache;
178
+ }, {});
179
+ const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
180
+ this._flagCache = newCache;
181
+ this._etag = (_a = response.httpResponse) === null || _a === void 0 ? void 0 : _a.headers.get('etag');
182
+ this._flagSetMetadataCache = ofrepCore.toFlagMetadata(typeof bulkSuccessResp.metadata === 'object' ? bulkSuccessResp.metadata : {});
183
+ return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
217
184
  }
218
185
  catch (error) {
219
186
  if (error instanceof ofrepCore.OFREPApiTooManyRequestsError && error.retryAfterDate !== null) {
@@ -255,7 +222,7 @@ class OFREPWebProvider {
255
222
  * @param defaultValue - default value
256
223
  * @private
257
224
  */
258
- _resolve(flagKey, type, defaultValue) {
225
+ _resolve(flagKey, defaultValue) {
259
226
  const resolved = this._flagCache[flagKey];
260
227
  if (!resolved) {
261
228
  return {
@@ -263,29 +230,16 @@ class OFREPWebProvider {
263
230
  flagMetadata: this._flagSetMetadataCache,
264
231
  reason: webSdk.StandardResolutionReasons.ERROR,
265
232
  errorCode: webSdk.ErrorCode.FLAG_NOT_FOUND,
266
- errorMessage: ErrorMessageMap[webSdk.ErrorCode.FLAG_NOT_FOUND],
233
+ errorMessage: ofrepCore.ErrorMessageMap[webSdk.ErrorCode.FLAG_NOT_FOUND],
267
234
  };
268
235
  }
269
- if (isResolutionError(resolved)) {
270
- return Object.assign(Object.assign({}, resolved), { value: defaultValue, errorMessage: ErrorMessageMap[resolved.errorCode] });
271
- }
272
- if (typeof resolved.value !== type) {
273
- return {
274
- value: defaultValue,
275
- flagMetadata: resolved.flagMetadata,
276
- reason: webSdk.StandardResolutionReasons.ERROR,
277
- errorCode: webSdk.ErrorCode.TYPE_MISMATCH,
278
- errorMessage: ErrorMessageMap[webSdk.ErrorCode.TYPE_MISMATCH],
279
- };
236
+ return this.responseToResolutionDetails(resolved, defaultValue);
237
+ }
238
+ responseToResolutionDetails(response, defaultValue) {
239
+ if (ofrepCore.isEvaluationFailureResponse(response)) {
240
+ return ofrepCore.handleEvaluationError(response, defaultValue);
280
241
  }
281
- return {
282
- variant: resolved.variant,
283
- value: resolved.value,
284
- flagMetadata: resolved.flagMetadata,
285
- errorCode: resolved.errorCode,
286
- errorMessage: resolved.errorMessage,
287
- reason: resolved.reason,
288
- };
242
+ return ofrepCore.toResolutionDetails(response, defaultValue);
289
243
  }
290
244
  /**
291
245
  * Start polling for flag updates, it will call the bulk update function every pollInterval
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { OFREPApi, OFREPApiUnauthorizedError, OFREPForbiddenError, OFREPApiTooManyRequestsError, OFREPApiFetchError, isEvaluationFailureResponse, isEvaluationSuccessResponse } from '@openfeature/ofrep-core';
2
- import { ErrorCode, OpenFeatureEventEmitter, StandardResolutionReasons, ProviderFatalError, ClientProviderEvents, OpenFeatureError, GeneralError } from '@openfeature/web-sdk';
1
+ import { OFREPApi, ErrorMessageMap, isEvaluationFailureResponse, handleEvaluationError, toResolutionDetails, OFREPApiUnauthorizedError, OFREPForbiddenError, OFREPApiTooManyRequestsError, OFREPApiFetchError, toFlagMetadata } from '@openfeature/ofrep-core';
2
+ import { OpenFeatureEventEmitter, ErrorCode, StandardResolutionReasons, ProviderFatalError, ClientProviderEvents, OpenFeatureError, GeneralError } from '@openfeature/web-sdk';
3
3
 
4
4
  /******************************************************************************
5
5
  Copyright (c) Microsoft Corporation.
@@ -39,23 +39,6 @@ var BulkEvaluationStatus;
39
39
  BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
40
40
  })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
41
41
 
42
- function isResolutionError(response) {
43
- if (!response || typeof response !== 'object') {
44
- return false;
45
- }
46
- return 'reason' in response && 'errorCode' in response && !('value' in response);
47
- }
48
-
49
- const ErrorMessageMap = {
50
- [ErrorCode.FLAG_NOT_FOUND]: 'Flag was not found',
51
- [ErrorCode.GENERAL]: 'General error',
52
- [ErrorCode.INVALID_CONTEXT]: 'Context is invalid or could be parsed',
53
- [ErrorCode.PARSE_ERROR]: 'Flag or flag configuration could not be parsed',
54
- [ErrorCode.PROVIDER_FATAL]: 'Provider is in a fatal error state',
55
- [ErrorCode.PROVIDER_NOT_READY]: 'Provider is not yet ready',
56
- [ErrorCode.TARGETING_KEY_MISSING]: 'Targeting key is missing',
57
- [ErrorCode.TYPE_MISMATCH]: 'Flag is not of expected type',
58
- };
59
42
  class OFREPWebProvider {
60
43
  constructor(options, logger) {
61
44
  var _a;
@@ -66,7 +49,6 @@ class OFREPWebProvider {
66
49
  this.runsOn = 'client';
67
50
  this.events = new OpenFeatureEventEmitter();
68
51
  this._flagCache = {};
69
- this._flagSetMetadataCache = {};
70
52
  this._options = options;
71
53
  this._logger = logger;
72
54
  this._etag = null;
@@ -105,16 +87,16 @@ class OFREPWebProvider {
105
87
  /* eslint-disable @typescript-eslint/no-unused-vars*/
106
88
  /* to make overrides easier we keep these unused vars */
107
89
  resolveBooleanEvaluation(flagKey, defaultValue, context) {
108
- return this._resolve(flagKey, 'boolean', defaultValue);
90
+ return this._resolve(flagKey, defaultValue);
109
91
  }
110
92
  resolveStringEvaluation(flagKey, defaultValue, context) {
111
- return this._resolve(flagKey, 'string', defaultValue);
93
+ return this._resolve(flagKey, defaultValue);
112
94
  }
113
95
  resolveNumberEvaluation(flagKey, defaultValue, context) {
114
- return this._resolve(flagKey, 'number', defaultValue);
96
+ return this._resolve(flagKey, defaultValue);
115
97
  }
116
98
  resolveObjectEvaluation(flagKey, defaultValue, context) {
117
- return this._resolve(flagKey, 'object', defaultValue);
99
+ return this._resolve(flagKey, defaultValue);
118
100
  }
119
101
  /**
120
102
  * onContextChange is called when the context changes, it will re-evaluate the flags with the new context
@@ -183,35 +165,20 @@ class OFREPWebProvider {
183
165
  throw new GeneralError(`Failed OFREP bulk evaluation request, status: ${response.httpStatus}`);
184
166
  }
185
167
  const bulkSuccessResp = response.value;
186
- const newCache = {};
187
- if ('flags' in bulkSuccessResp && Array.isArray(bulkSuccessResp.flags)) {
188
- bulkSuccessResp.flags.forEach((evalResp) => {
189
- if (isEvaluationFailureResponse(evalResp)) {
190
- newCache[evalResp.key] = {
191
- reason: StandardResolutionReasons.ERROR,
192
- flagMetadata: evalResp.metadata,
193
- errorCode: evalResp.errorCode,
194
- errorDetails: evalResp.errorDetails,
195
- };
196
- }
197
- if (isEvaluationSuccessResponse(evalResp) && evalResp.key) {
198
- newCache[evalResp.key] = {
199
- value: evalResp.value,
200
- variant: evalResp.variant,
201
- reason: evalResp.reason,
202
- flagMetadata: evalResp.metadata,
203
- };
204
- }
205
- });
206
- const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
207
- this._flagCache = newCache;
208
- this._etag = (_a = response.httpResponse) === null || _a === void 0 ? void 0 : _a.headers.get('etag');
209
- this._flagSetMetadataCache = typeof bulkSuccessResp.metadata === 'object' ? bulkSuccessResp.metadata : {};
210
- return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
211
- }
212
- else {
168
+ if (!('flags' in bulkSuccessResp) || !Array.isArray(bulkSuccessResp.flags)) {
213
169
  throw new Error('No flags in OFREP bulk evaluation response');
214
170
  }
171
+ const newCache = bulkSuccessResp.flags.reduce((currentCache, currentResponse) => {
172
+ if (currentResponse.key) {
173
+ currentCache[currentResponse.key] = currentResponse;
174
+ }
175
+ return currentCache;
176
+ }, {});
177
+ const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
178
+ this._flagCache = newCache;
179
+ this._etag = (_a = response.httpResponse) === null || _a === void 0 ? void 0 : _a.headers.get('etag');
180
+ this._flagSetMetadataCache = toFlagMetadata(typeof bulkSuccessResp.metadata === 'object' ? bulkSuccessResp.metadata : {});
181
+ return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
215
182
  }
216
183
  catch (error) {
217
184
  if (error instanceof OFREPApiTooManyRequestsError && error.retryAfterDate !== null) {
@@ -253,7 +220,7 @@ class OFREPWebProvider {
253
220
  * @param defaultValue - default value
254
221
  * @private
255
222
  */
256
- _resolve(flagKey, type, defaultValue) {
223
+ _resolve(flagKey, defaultValue) {
257
224
  const resolved = this._flagCache[flagKey];
258
225
  if (!resolved) {
259
226
  return {
@@ -264,26 +231,13 @@ class OFREPWebProvider {
264
231
  errorMessage: ErrorMessageMap[ErrorCode.FLAG_NOT_FOUND],
265
232
  };
266
233
  }
267
- if (isResolutionError(resolved)) {
268
- return Object.assign(Object.assign({}, resolved), { value: defaultValue, errorMessage: ErrorMessageMap[resolved.errorCode] });
269
- }
270
- if (typeof resolved.value !== type) {
271
- return {
272
- value: defaultValue,
273
- flagMetadata: resolved.flagMetadata,
274
- reason: StandardResolutionReasons.ERROR,
275
- errorCode: ErrorCode.TYPE_MISMATCH,
276
- errorMessage: ErrorMessageMap[ErrorCode.TYPE_MISMATCH],
277
- };
234
+ return this.responseToResolutionDetails(resolved, defaultValue);
235
+ }
236
+ responseToResolutionDetails(response, defaultValue) {
237
+ if (isEvaluationFailureResponse(response)) {
238
+ return handleEvaluationError(response, defaultValue);
278
239
  }
279
- return {
280
- variant: resolved.variant,
281
- value: resolved.value,
282
- flagMetadata: resolved.flagMetadata,
283
- errorCode: resolved.errorCode,
284
- errorMessage: resolved.errorMessage,
285
- reason: resolved.reason,
286
- };
240
+ return toResolutionDetails(response, defaultValue);
287
241
  }
288
242
  /**
289
243
  * Start polling for flag updates, it will call the bulk update function every pollInterval
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfeature/ofrep-web-provider",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "license": "Apache-2.0",
5
5
  "main": "./index.cjs.js",
6
6
  "typings": "./src/index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "@openfeature/web-sdk": "^1.4.0"
13
13
  },
14
14
  "dependencies": {
15
- "@openfeature/ofrep-core": "^1.0.0"
15
+ "@openfeature/ofrep-core": "^2.0.0"
16
16
  },
17
17
  "exports": {
18
18
  "./package.json": "./package.json",
@@ -1,10 +1,10 @@
1
- import type { FlagMetadata, FlagValue, ResolutionDetails } from '@openfeature/web-sdk';
2
- import type { ResolutionError } from './resolution-error';
1
+ import type { FlagMetadata } from '@openfeature/web-sdk';
2
+ import type { EvaluationResponse } from '@openfeature/ofrep-core';
3
3
  /**
4
4
  * Cache of flag values from bulk evaluation.
5
5
  */
6
6
  export type FlagCache = {
7
- [key: string]: ResolutionDetails<FlagValue> | ResolutionError;
7
+ [key: string]: EvaluationResponse;
8
8
  };
9
9
  /**
10
10
  * Cache of metadata from bulk evaluation.
@@ -17,7 +17,7 @@ export declare class OFREPWebProvider implements Provider {
17
17
  private _pollingInterval;
18
18
  private _retryPollingAfter;
19
19
  private _flagCache;
20
- private _flagSetMetadataCache;
20
+ private _flagSetMetadataCache?;
21
21
  private _context;
22
22
  private _pollingIntervalId?;
23
23
  constructor(options: OFREPWebProviderOptions, logger?: Logger);
@@ -72,6 +72,7 @@ export declare class OFREPWebProvider implements Provider {
72
72
  * @private
73
73
  */
74
74
  private _resolve;
75
+ private responseToResolutionDetails;
75
76
  /**
76
77
  * Start polling for flag updates, it will call the bulk update function every pollInterval
77
78
  * @private