@openfeature/ofrep-web-provider 0.3.2 → 0.3.4
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 +33 -79
- package/index.esm.js +34 -80
- package/package.json +1 -2
- package/src/lib/model/in-memory-cache.d.ts +3 -3
- package/src/lib/model/ofrep-web-provider-options.d.ts +1 -1
- package/src/lib/model/resolution-error.d.ts +1 -1
- package/src/lib/ofrep-web-provider.d.ts +6 -4
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,12 +51,11 @@ 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;
|
|
75
57
|
this._ofrepAPI = new ofrepCore.OFREPApi(this._options, this._options.fetchImplementation);
|
|
76
|
-
this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !==
|
|
58
|
+
this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !== void 0 ? _a : this.DEFAULT_POLL_INTERVAL;
|
|
77
59
|
}
|
|
78
60
|
/**
|
|
79
61
|
* Returns a shallow copy of the flag cache, which is updated at initialization/context-change/configuration-change once the flags are re-evaluated.
|
|
@@ -86,7 +68,7 @@ class OFREPWebProvider {
|
|
|
86
68
|
* @param context - the context to use for the evaluation
|
|
87
69
|
*/
|
|
88
70
|
initialize(context) {
|
|
89
|
-
return __awaiter(this,
|
|
71
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
90
72
|
var _a;
|
|
91
73
|
try {
|
|
92
74
|
this._context = context;
|
|
@@ -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
|
|
@@ -125,7 +107,7 @@ class OFREPWebProvider {
|
|
|
125
107
|
* @param newContext - the new evaluation context
|
|
126
108
|
*/
|
|
127
109
|
onContextChange(oldContext, newContext) {
|
|
128
|
-
return __awaiter(this,
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
129
111
|
var _a, _b, _c;
|
|
130
112
|
try {
|
|
131
113
|
this._context = newContext;
|
|
@@ -138,17 +120,17 @@ class OFREPWebProvider {
|
|
|
138
120
|
}
|
|
139
121
|
catch (error) {
|
|
140
122
|
if (error instanceof ofrepCore.OFREPApiTooManyRequestsError) {
|
|
141
|
-
(_a = this.events) === null || _a ===
|
|
123
|
+
(_a = this.events) === null || _a === void 0 ? void 0 : _a.emit(webSdk.ClientProviderEvents.Stale, { message: `${error.name}: ${error.message}` });
|
|
142
124
|
return;
|
|
143
125
|
}
|
|
144
126
|
if (error instanceof webSdk.OpenFeatureError ||
|
|
145
127
|
error instanceof ofrepCore.OFREPApiFetchError ||
|
|
146
128
|
error instanceof ofrepCore.OFREPApiUnauthorizedError ||
|
|
147
129
|
error instanceof ofrepCore.OFREPForbiddenError) {
|
|
148
|
-
(_b = this.events) === null || _b ===
|
|
130
|
+
(_b = this.events) === null || _b === void 0 ? void 0 : _b.emit(webSdk.ClientProviderEvents.Error, { message: `${error.name}: ${error.message}` });
|
|
149
131
|
return;
|
|
150
132
|
}
|
|
151
|
-
(_c = this.events) === null || _c ===
|
|
133
|
+
(_c = this.events) === null || _c === void 0 ? void 0 : _c.emit(webSdk.ClientProviderEvents.Error, { message: `Unknown error: ${error}` });
|
|
152
134
|
}
|
|
153
135
|
});
|
|
154
136
|
}
|
|
@@ -170,7 +152,7 @@ class OFREPWebProvider {
|
|
|
170
152
|
* @throws GeneralError if the API returned a 400 with an unknown error code
|
|
171
153
|
*/
|
|
172
154
|
_fetchFlags(context) {
|
|
173
|
-
return __awaiter(this,
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
174
156
|
var _a;
|
|
175
157
|
try {
|
|
176
158
|
const evalReq = {
|
|
@@ -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,36 +230,23 @@ 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
|
|
292
246
|
* @private
|
|
293
247
|
*/
|
|
294
248
|
startPolling() {
|
|
295
|
-
this._pollingIntervalId = setInterval(() => __awaiter(this,
|
|
249
|
+
this._pollingIntervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
296
250
|
var _a, _b;
|
|
297
251
|
try {
|
|
298
252
|
const now = new Date();
|
|
@@ -308,7 +262,7 @@ class OFREPWebProvider {
|
|
|
308
262
|
}
|
|
309
263
|
}
|
|
310
264
|
catch (error) {
|
|
311
|
-
(_b = this.events) === null || _b ===
|
|
265
|
+
(_b = this.events) === null || _b === void 0 ? void 0 : _b.emit(webSdk.ClientProviderEvents.Stale, { message: `Error while polling: ${error}` });
|
|
312
266
|
}
|
|
313
267
|
}), this._pollingInterval);
|
|
314
268
|
}
|
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,12 +49,11 @@ 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;
|
|
73
55
|
this._ofrepAPI = new OFREPApi(this._options, this._options.fetchImplementation);
|
|
74
|
-
this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !==
|
|
56
|
+
this._pollingInterval = (_a = this._options.pollInterval) !== null && _a !== void 0 ? _a : this.DEFAULT_POLL_INTERVAL;
|
|
75
57
|
}
|
|
76
58
|
/**
|
|
77
59
|
* Returns a shallow copy of the flag cache, which is updated at initialization/context-change/configuration-change once the flags are re-evaluated.
|
|
@@ -84,7 +66,7 @@ class OFREPWebProvider {
|
|
|
84
66
|
* @param context - the context to use for the evaluation
|
|
85
67
|
*/
|
|
86
68
|
initialize(context) {
|
|
87
|
-
return __awaiter(this,
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
88
70
|
var _a;
|
|
89
71
|
try {
|
|
90
72
|
this._context = context;
|
|
@@ -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
|
|
@@ -123,7 +105,7 @@ class OFREPWebProvider {
|
|
|
123
105
|
* @param newContext - the new evaluation context
|
|
124
106
|
*/
|
|
125
107
|
onContextChange(oldContext, newContext) {
|
|
126
|
-
return __awaiter(this,
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
109
|
var _a, _b, _c;
|
|
128
110
|
try {
|
|
129
111
|
this._context = newContext;
|
|
@@ -136,17 +118,17 @@ class OFREPWebProvider {
|
|
|
136
118
|
}
|
|
137
119
|
catch (error) {
|
|
138
120
|
if (error instanceof OFREPApiTooManyRequestsError) {
|
|
139
|
-
(_a = this.events) === null || _a ===
|
|
121
|
+
(_a = this.events) === null || _a === void 0 ? void 0 : _a.emit(ClientProviderEvents.Stale, { message: `${error.name}: ${error.message}` });
|
|
140
122
|
return;
|
|
141
123
|
}
|
|
142
124
|
if (error instanceof OpenFeatureError ||
|
|
143
125
|
error instanceof OFREPApiFetchError ||
|
|
144
126
|
error instanceof OFREPApiUnauthorizedError ||
|
|
145
127
|
error instanceof OFREPForbiddenError) {
|
|
146
|
-
(_b = this.events) === null || _b ===
|
|
128
|
+
(_b = this.events) === null || _b === void 0 ? void 0 : _b.emit(ClientProviderEvents.Error, { message: `${error.name}: ${error.message}` });
|
|
147
129
|
return;
|
|
148
130
|
}
|
|
149
|
-
(_c = this.events) === null || _c ===
|
|
131
|
+
(_c = this.events) === null || _c === void 0 ? void 0 : _c.emit(ClientProviderEvents.Error, { message: `Unknown error: ${error}` });
|
|
150
132
|
}
|
|
151
133
|
});
|
|
152
134
|
}
|
|
@@ -168,7 +150,7 @@ class OFREPWebProvider {
|
|
|
168
150
|
* @throws GeneralError if the API returned a 400 with an unknown error code
|
|
169
151
|
*/
|
|
170
152
|
_fetchFlags(context) {
|
|
171
|
-
return __awaiter(this,
|
|
153
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
172
154
|
var _a;
|
|
173
155
|
try {
|
|
174
156
|
const evalReq = {
|
|
@@ -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,33 +231,20 @@ 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
|
|
290
244
|
* @private
|
|
291
245
|
*/
|
|
292
246
|
startPolling() {
|
|
293
|
-
this._pollingIntervalId = setInterval(() => __awaiter(this,
|
|
247
|
+
this._pollingIntervalId = setInterval(() => __awaiter(this, void 0, void 0, function* () {
|
|
294
248
|
var _a, _b;
|
|
295
249
|
try {
|
|
296
250
|
const now = new Date();
|
|
@@ -306,7 +260,7 @@ class OFREPWebProvider {
|
|
|
306
260
|
}
|
|
307
261
|
}
|
|
308
262
|
catch (error) {
|
|
309
|
-
(_b = this.events) === null || _b ===
|
|
263
|
+
(_b = this.events) === null || _b === void 0 ? void 0 : _b.emit(ClientProviderEvents.Stale, { message: `Error while polling: ${error}` });
|
|
310
264
|
}
|
|
311
265
|
}), this._pollingInterval);
|
|
312
266
|
}
|
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.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./index.cjs.js",
|
|
6
6
|
"typings": "./src/index.d.ts",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"@openfeature/web-sdk": "^1.4.0"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"undici": "^5.0.0",
|
|
16
15
|
"@openfeature/ofrep-core": "^1.0.0"
|
|
17
16
|
},
|
|
18
17
|
"exports": {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { FlagMetadata
|
|
2
|
-
import {
|
|
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.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OFREPProviderBaseOptions } from '@openfeature/ofrep-core';
|
|
1
|
+
import type { OFREPProviderBaseOptions } from '@openfeature/ofrep-core';
|
|
2
2
|
export type OFREPWebProviderOptions = OFREPProviderBaseOptions & {
|
|
3
3
|
/**
|
|
4
4
|
* pollInterval is the time in milliseconds to wait between we call the OFREP
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { EvaluationContext, Hook, JsonValue, Logger,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { EvaluationContext, Hook, JsonValue, Logger, Provider, ResolutionDetails } from '@openfeature/web-sdk';
|
|
2
|
+
import { OpenFeatureEventEmitter } from '@openfeature/web-sdk';
|
|
3
|
+
import type { FlagCache } from './model/in-memory-cache';
|
|
4
|
+
import type { OFREPWebProviderOptions } from './model/ofrep-web-provider-options';
|
|
4
5
|
export declare class OFREPWebProvider implements Provider {
|
|
5
6
|
DEFAULT_POLL_INTERVAL: number;
|
|
6
7
|
readonly metadata: {
|
|
@@ -16,7 +17,7 @@ export declare class OFREPWebProvider implements Provider {
|
|
|
16
17
|
private _pollingInterval;
|
|
17
18
|
private _retryPollingAfter;
|
|
18
19
|
private _flagCache;
|
|
19
|
-
private _flagSetMetadataCache
|
|
20
|
+
private _flagSetMetadataCache?;
|
|
20
21
|
private _context;
|
|
21
22
|
private _pollingIntervalId?;
|
|
22
23
|
constructor(options: OFREPWebProviderOptions, logger?: Logger);
|
|
@@ -71,6 +72,7 @@ export declare class OFREPWebProvider implements Provider {
|
|
|
71
72
|
* @private
|
|
72
73
|
*/
|
|
73
74
|
private _resolve;
|
|
75
|
+
private responseToResolutionDetails;
|
|
74
76
|
/**
|
|
75
77
|
* Start polling for flag updates, it will call the bulk update function every pollInterval
|
|
76
78
|
* @private
|