@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 +1 -1
- package/index.cjs.js +24 -70
- package/index.esm.js +25 -71
- package/package.json +2 -2
- package/src/lib/model/in-memory-cache.d.ts +3 -3
- package/src/lib/ofrep-web-provider.d.ts +2 -1
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
|
|
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,
|
|
92
|
+
return this._resolve(flagKey, defaultValue);
|
|
111
93
|
}
|
|
112
94
|
resolveStringEvaluation(flagKey, defaultValue, context) {
|
|
113
|
-
return this._resolve(flagKey,
|
|
95
|
+
return this._resolve(flagKey, defaultValue);
|
|
114
96
|
}
|
|
115
97
|
resolveNumberEvaluation(flagKey, defaultValue, context) {
|
|
116
|
-
return this._resolve(flagKey,
|
|
98
|
+
return this._resolve(flagKey, defaultValue);
|
|
117
99
|
}
|
|
118
100
|
resolveObjectEvaluation(flagKey, defaultValue, context) {
|
|
119
|
-
return this._resolve(flagKey,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (
|
|
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,
|
|
2
|
-
import {
|
|
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,
|
|
90
|
+
return this._resolve(flagKey, defaultValue);
|
|
109
91
|
}
|
|
110
92
|
resolveStringEvaluation(flagKey, defaultValue, context) {
|
|
111
|
-
return this._resolve(flagKey,
|
|
93
|
+
return this._resolve(flagKey, defaultValue);
|
|
112
94
|
}
|
|
113
95
|
resolveNumberEvaluation(flagKey, defaultValue, context) {
|
|
114
|
-
return this._resolve(flagKey,
|
|
96
|
+
return this._resolve(flagKey, defaultValue);
|
|
115
97
|
}
|
|
116
98
|
resolveObjectEvaluation(flagKey, defaultValue, context) {
|
|
117
|
-
return this._resolve(flagKey,
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (
|
|
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
|
+
"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": "^
|
|
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
|
|
2
|
-
import type {
|
|
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]:
|
|
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
|