@openfeature/ofrep-web-provider 0.1.5 → 0.3.0

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/index.cjs.js CHANGED
@@ -3,9 +3,15 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var tslib = require('tslib');
6
- var webSdk = require('@openfeature/web-sdk');
7
- var ofrepCore = require('@openfeature/ofrep-core');
8
6
  var core = require('@openfeature/core');
7
+ var ofrepCore = require('@openfeature/ofrep-core');
8
+ var webSdk = require('@openfeature/web-sdk');
9
+
10
+ var BulkEvaluationStatus;
11
+ (function (BulkEvaluationStatus) {
12
+ BulkEvaluationStatus["SUCCESS_NO_CHANGES"] = "SUCCESS_NO_CHANGES";
13
+ BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
14
+ })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
9
15
 
10
16
  function isResolutionError(response) {
11
17
  if (!response || typeof response !== 'object') {
@@ -14,12 +20,6 @@ function isResolutionError(response) {
14
20
  return 'reason' in response && 'errorCode' in response && !('value' in response);
15
21
  }
16
22
 
17
- var BulkEvaluationStatus;
18
- (function (BulkEvaluationStatus) {
19
- BulkEvaluationStatus["SUCCESS_NO_CHANGES"] = "SUCCESS_NO_CHANGES";
20
- BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
21
- })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
22
-
23
23
  class OFREPWebProvider {
24
24
  constructor(options, logger) {
25
25
  var _a;
@@ -29,13 +29,19 @@ class OFREPWebProvider {
29
29
  };
30
30
  this.runsOn = 'client';
31
31
  this.events = new webSdk.OpenFeatureEventEmitter();
32
- this._cache = {};
32
+ this._flagCache = {};
33
33
  this._options = options;
34
34
  this._logger = logger;
35
35
  this._etag = null;
36
- this._ofrepAPI = new ofrepCore.OFREPApi(this._options.baseUrl, this._options.fetchImplementation);
36
+ this._ofrepAPI = new ofrepCore.OFREPApi(this._options, this._options.fetchImplementation);
37
37
  this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !== void 0 ? _a : this.DEFAULT_POLL_INTERVAL;
38
38
  }
39
+ /**
40
+ * Returns a shallow copy of the flag cache, which is updated at initialization/context-change/configuration-change once the flags are re-evaluated.
41
+ */
42
+ get flagCache() {
43
+ return Object.assign({}, this._flagCache);
44
+ }
39
45
  /**
40
46
  * Initialize the provider, it will evaluate the flags and start the polling if it is not disabled.
41
47
  * @param context - the context to use for the evaluation
@@ -59,18 +65,21 @@ class OFREPWebProvider {
59
65
  }
60
66
  });
61
67
  }
62
- resolveBooleanEvaluation(flagKey) {
68
+ /* eslint-disable @typescript-eslint/no-unused-vars*/
69
+ /* to make overrides easier we keep these unused vars */
70
+ resolveBooleanEvaluation(flagKey, defaultValue, context) {
63
71
  return this.evaluate(flagKey, 'boolean');
64
72
  }
65
- resolveStringEvaluation(flagKey) {
73
+ resolveStringEvaluation(flagKey, defaultValue, context) {
66
74
  return this.evaluate(flagKey, 'string');
67
75
  }
68
- resolveNumberEvaluation(flagKey) {
76
+ resolveNumberEvaluation(flagKey, defaultValue, context) {
69
77
  return this.evaluate(flagKey, 'number');
70
78
  }
71
- resolveObjectEvaluation(flagKey) {
79
+ resolveObjectEvaluation(flagKey, defaultValue, context) {
72
80
  return this.evaluate(flagKey, 'object');
73
81
  }
82
+ /* eslint-enable @typescript-eslint/no-unused-vars */
74
83
  /**
75
84
  * onContextChange is called when the context changes, it will re-evaluate the flags with the new context
76
85
  * and update the cache.
@@ -129,10 +138,7 @@ class OFREPWebProvider {
129
138
  const evalReq = {
130
139
  context,
131
140
  };
132
- const options = Object.assign({ headers: new Headers({
133
- 'Content-Type': 'application/json',
134
- }) }, (this._etag !== null ? { headers: { 'If-None-Match': this._etag } } : {}));
135
- const response = yield this._ofrepAPI.postBulkEvaluateFlags(evalReq, options);
141
+ const response = yield this._ofrepAPI.postBulkEvaluateFlags(evalReq, this._etag);
136
142
  if (response.httpStatus === 304) {
137
143
  // nothing has changed since last time, we are doing nothing
138
144
  return { status: BulkEvaluationStatus.SUCCESS_NO_CHANGES, flags: [] };
@@ -159,8 +165,8 @@ class OFREPWebProvider {
159
165
  };
160
166
  }
161
167
  });
162
- const listUpdatedFlags = this._getListUpdatedFlags(this._cache, newCache);
163
- this._cache = newCache;
168
+ const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
169
+ this._flagCache = newCache;
164
170
  this._etag = (_b = response.httpResponse) === null || _b === void 0 ? void 0 : _b.headers.get('etag');
165
171
  return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
166
172
  }
@@ -204,7 +210,7 @@ class OFREPWebProvider {
204
210
  * @private
205
211
  */
206
212
  evaluate(flagKey, type) {
207
- const resolved = this._cache[flagKey];
213
+ const resolved = this._flagCache[flagKey];
208
214
  if (!resolved) {
209
215
  throw new webSdk.FlagNotFoundError(`flag key ${flagKey} not found in cache`);
210
216
  }
package/index.esm.js CHANGED
@@ -1,7 +1,13 @@
1
1
  import { __awaiter } from 'tslib';
2
- import { OpenFeatureEventEmitter, ProviderFatalError, ClientProviderEvents, OpenFeatureError, FlagNotFoundError, GeneralError, TypeMismatchError } from '@openfeature/web-sdk';
3
- import { OFREPApi, OFREPApiUnauthorizedError, OFREPForbiddenError, OFREPApiTooManyRequestsError, OFREPApiFetchError, handleEvaluationError, isEvaluationFailureResponse, isEvaluationSuccessResponse, EvaluationFailureErrorCode } from '@openfeature/ofrep-core';
4
2
  import { StandardResolutionReasons, ParseError, InvalidContextError, TargetingKeyMissingError } from '@openfeature/core';
3
+ import { OFREPApi, OFREPApiUnauthorizedError, OFREPForbiddenError, OFREPApiTooManyRequestsError, OFREPApiFetchError, handleEvaluationError, isEvaluationFailureResponse, isEvaluationSuccessResponse, EvaluationFailureErrorCode } from '@openfeature/ofrep-core';
4
+ import { OpenFeatureEventEmitter, ProviderFatalError, ClientProviderEvents, OpenFeatureError, FlagNotFoundError, GeneralError, TypeMismatchError } from '@openfeature/web-sdk';
5
+
6
+ var BulkEvaluationStatus;
7
+ (function (BulkEvaluationStatus) {
8
+ BulkEvaluationStatus["SUCCESS_NO_CHANGES"] = "SUCCESS_NO_CHANGES";
9
+ BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
10
+ })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
5
11
 
6
12
  function isResolutionError(response) {
7
13
  if (!response || typeof response !== 'object') {
@@ -10,12 +16,6 @@ function isResolutionError(response) {
10
16
  return 'reason' in response && 'errorCode' in response && !('value' in response);
11
17
  }
12
18
 
13
- var BulkEvaluationStatus;
14
- (function (BulkEvaluationStatus) {
15
- BulkEvaluationStatus["SUCCESS_NO_CHANGES"] = "SUCCESS_NO_CHANGES";
16
- BulkEvaluationStatus["SUCCESS_WITH_CHANGES"] = "SUCCESS_WITH_CHANGES";
17
- })(BulkEvaluationStatus || (BulkEvaluationStatus = {}));
18
-
19
19
  class OFREPWebProvider {
20
20
  constructor(options, logger) {
21
21
  var _a;
@@ -25,13 +25,19 @@ class OFREPWebProvider {
25
25
  };
26
26
  this.runsOn = 'client';
27
27
  this.events = new OpenFeatureEventEmitter();
28
- this._cache = {};
28
+ this._flagCache = {};
29
29
  this._options = options;
30
30
  this._logger = logger;
31
31
  this._etag = null;
32
- this._ofrepAPI = new OFREPApi(this._options.baseUrl, this._options.fetchImplementation);
32
+ this._ofrepAPI = new OFREPApi(this._options, this._options.fetchImplementation);
33
33
  this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !== void 0 ? _a : this.DEFAULT_POLL_INTERVAL;
34
34
  }
35
+ /**
36
+ * Returns a shallow copy of the flag cache, which is updated at initialization/context-change/configuration-change once the flags are re-evaluated.
37
+ */
38
+ get flagCache() {
39
+ return Object.assign({}, this._flagCache);
40
+ }
35
41
  /**
36
42
  * Initialize the provider, it will evaluate the flags and start the polling if it is not disabled.
37
43
  * @param context - the context to use for the evaluation
@@ -55,18 +61,21 @@ class OFREPWebProvider {
55
61
  }
56
62
  });
57
63
  }
58
- resolveBooleanEvaluation(flagKey) {
64
+ /* eslint-disable @typescript-eslint/no-unused-vars*/
65
+ /* to make overrides easier we keep these unused vars */
66
+ resolveBooleanEvaluation(flagKey, defaultValue, context) {
59
67
  return this.evaluate(flagKey, 'boolean');
60
68
  }
61
- resolveStringEvaluation(flagKey) {
69
+ resolveStringEvaluation(flagKey, defaultValue, context) {
62
70
  return this.evaluate(flagKey, 'string');
63
71
  }
64
- resolveNumberEvaluation(flagKey) {
72
+ resolveNumberEvaluation(flagKey, defaultValue, context) {
65
73
  return this.evaluate(flagKey, 'number');
66
74
  }
67
- resolveObjectEvaluation(flagKey) {
75
+ resolveObjectEvaluation(flagKey, defaultValue, context) {
68
76
  return this.evaluate(flagKey, 'object');
69
77
  }
78
+ /* eslint-enable @typescript-eslint/no-unused-vars */
70
79
  /**
71
80
  * onContextChange is called when the context changes, it will re-evaluate the flags with the new context
72
81
  * and update the cache.
@@ -125,10 +134,7 @@ class OFREPWebProvider {
125
134
  const evalReq = {
126
135
  context,
127
136
  };
128
- const options = Object.assign({ headers: new Headers({
129
- 'Content-Type': 'application/json',
130
- }) }, (this._etag !== null ? { headers: { 'If-None-Match': this._etag } } : {}));
131
- const response = yield this._ofrepAPI.postBulkEvaluateFlags(evalReq, options);
137
+ const response = yield this._ofrepAPI.postBulkEvaluateFlags(evalReq, this._etag);
132
138
  if (response.httpStatus === 304) {
133
139
  // nothing has changed since last time, we are doing nothing
134
140
  return { status: BulkEvaluationStatus.SUCCESS_NO_CHANGES, flags: [] };
@@ -155,8 +161,8 @@ class OFREPWebProvider {
155
161
  };
156
162
  }
157
163
  });
158
- const listUpdatedFlags = this._getListUpdatedFlags(this._cache, newCache);
159
- this._cache = newCache;
164
+ const listUpdatedFlags = this._getListUpdatedFlags(this._flagCache, newCache);
165
+ this._flagCache = newCache;
160
166
  this._etag = (_b = response.httpResponse) === null || _b === void 0 ? void 0 : _b.headers.get('etag');
161
167
  return { status: BulkEvaluationStatus.SUCCESS_WITH_CHANGES, flags: listUpdatedFlags };
162
168
  }
@@ -200,7 +206,7 @@ class OFREPWebProvider {
200
206
  * @private
201
207
  */
202
208
  evaluate(flagKey, type) {
203
- const resolved = this._cache[flagKey];
209
+ const resolved = this._flagCache[flagKey];
204
210
  if (!resolved) {
205
211
  throw new FlagNotFoundError(`flag key ${flagKey} not found in cache`);
206
212
  }
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@openfeature/ofrep-web-provider",
3
- "version": "0.1.5",
3
+ "version": "0.3.0",
4
4
  "dependencies": {
5
- "tslib": "^2.3.0"
5
+ "tslib": "^2.3.0",
6
+ "@openfeature/ofrep-core": "0.2.0"
6
7
  },
7
8
  "main": "./index.cjs.js",
8
9
  "typings": "./src/index.d.ts",
@@ -11,8 +12,7 @@
11
12
  "current-version": "echo $npm_package_version"
12
13
  },
13
14
  "peerDependencies": {
14
- "@openfeature/web-sdk": ">=0.4.0",
15
- "@openfeature/ofrep-core": "^0.1.5"
15
+ "@openfeature/web-sdk": ">=0.4.0"
16
16
  },
17
17
  "exports": {
18
18
  "./package.json": "./package.json",
@@ -1,8 +1,8 @@
1
1
  import { FlagValue, ResolutionDetails } from '@openfeature/web-sdk';
2
2
  import { ResolutionError } from './resolution-error';
3
3
  /**
4
- * inMemoryCache is a type representing the internal cache of the flags.
4
+ * FlagCache is a type representing the internal cache of the flags.
5
5
  */
6
- export type InMemoryCache = {
6
+ export type FlagCache = {
7
7
  [key: string]: ResolutionDetails<FlagValue> | ResolutionError;
8
8
  };
@@ -1,4 +1,5 @@
1
1
  import { EvaluationContext, Hook, JsonValue, Logger, OpenFeatureEventEmitter, Provider, ResolutionDetails } from '@openfeature/web-sdk';
2
+ import { FlagCache } from './model/in-memory-cache';
2
3
  import { OFREPWebProviderOptions } from './model/ofrep-web-provider-options';
3
4
  export declare class OFREPWebProvider implements Provider {
4
5
  DEFAULT_POLL_INTERVAL: number;
@@ -6,27 +7,31 @@ export declare class OFREPWebProvider implements Provider {
6
7
  name: string;
7
8
  };
8
9
  readonly runsOn = "client";
9
- events: OpenFeatureEventEmitter;
10
- hooks?: Hook[] | undefined;
10
+ readonly events: OpenFeatureEventEmitter;
11
+ readonly hooks?: Hook[] | undefined;
11
12
  private _logger?;
12
13
  private _options;
13
14
  private _ofrepAPI;
14
15
  private _etag;
15
16
  private _pollingInterval;
16
17
  private _retryPollingAfter;
17
- private _cache;
18
+ private _flagCache;
18
19
  private _context;
19
20
  private _pollingIntervalId?;
20
21
  constructor(options: OFREPWebProviderOptions, logger?: Logger);
22
+ /**
23
+ * Returns a shallow copy of the flag cache, which is updated at initialization/context-change/configuration-change once the flags are re-evaluated.
24
+ */
25
+ get flagCache(): FlagCache;
21
26
  /**
22
27
  * Initialize the provider, it will evaluate the flags and start the polling if it is not disabled.
23
28
  * @param context - the context to use for the evaluation
24
29
  */
25
- initialize?(context?: EvaluationContext | undefined): Promise<void>;
26
- resolveBooleanEvaluation(flagKey: string): ResolutionDetails<boolean>;
27
- resolveStringEvaluation(flagKey: string): ResolutionDetails<string>;
28
- resolveNumberEvaluation(flagKey: string): ResolutionDetails<number>;
29
- resolveObjectEvaluation<T extends JsonValue>(flagKey: string): ResolutionDetails<T>;
30
+ initialize(context?: EvaluationContext | undefined): Promise<void>;
31
+ resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext): ResolutionDetails<boolean>;
32
+ resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext): ResolutionDetails<string>;
33
+ resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext): ResolutionDetails<number>;
34
+ resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext): ResolutionDetails<T>;
30
35
  /**
31
36
  * onContextChange is called when the context changes, it will re-evaluate the flags with the new context
32
37
  * and update the cache.