@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 +27 -21
- package/index.esm.js +27 -21
- package/package.json +4 -4
- package/src/lib/model/in-memory-cache.d.ts +2 -2
- package/src/lib/ofrep-web-provider.d.ts +13 -8
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
163
|
-
this.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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.
|
|
159
|
-
this.
|
|
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.
|
|
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.
|
|
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
|
-
*
|
|
4
|
+
* FlagCache is a type representing the internal cache of the flags.
|
|
5
5
|
*/
|
|
6
|
-
export type
|
|
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
|
|
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
|
|
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.
|