@openfeature/server-sdk 1.9.1 → 1.11.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/README.md +17 -12
- package/dist/cjs/index.js +140 -199
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +140 -202
- package/dist/esm/index.js.map +1 -1
- package/dist/types.d.ts +4 -637
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
<img alt="Specification" src="https://img.shields.io/static/v1?label=specification&message=v0.7.0&color=yellow&style=for-the-badge" />
|
|
17
17
|
</a>
|
|
18
18
|
<!-- x-release-please-start-version -->
|
|
19
|
-
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.
|
|
20
|
-
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.
|
|
19
|
+
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.11.0">
|
|
20
|
+
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.11.0&color=blue&style=for-the-badge" />
|
|
21
21
|
</a>
|
|
22
22
|
<!-- x-release-please-end -->
|
|
23
23
|
<br/>
|
|
@@ -271,43 +271,48 @@ This can be a new repository or included in [the existing contrib repository](ht
|
|
|
271
271
|
You’ll then need to write the provider by implementing the [Provider interface](./src/provider/provider.ts) exported by the OpenFeature SDK.
|
|
272
272
|
|
|
273
273
|
```ts
|
|
274
|
-
import {
|
|
274
|
+
import {
|
|
275
|
+
AnyProviderEvent,
|
|
276
|
+
EvaluationContext,
|
|
277
|
+
Hook,
|
|
278
|
+
JsonValue,
|
|
279
|
+
Logger,
|
|
280
|
+
Provider,
|
|
281
|
+
ProviderEventEmitter,
|
|
282
|
+
ProviderStatus,
|
|
283
|
+
ResolutionDetails
|
|
284
|
+
} from '@openfeature/server-sdk';
|
|
275
285
|
|
|
276
286
|
// implement the provider interface
|
|
277
287
|
class MyProvider implements Provider {
|
|
278
288
|
// Adds runtime validation that the provider is used with the expected SDK
|
|
279
289
|
public readonly runsOn = 'server';
|
|
280
|
-
|
|
281
290
|
readonly metadata = {
|
|
282
291
|
name: 'My Provider',
|
|
283
292
|
} as const;
|
|
284
|
-
|
|
285
293
|
// Optional provider managed hooks
|
|
286
|
-
hooks?: Hook
|
|
287
|
-
|
|
294
|
+
hooks?: Hook[];
|
|
288
295
|
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<boolean>> {
|
|
289
296
|
// code to evaluate a boolean
|
|
290
297
|
}
|
|
291
|
-
|
|
292
298
|
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<string>> {
|
|
293
299
|
// code to evaluate a string
|
|
294
300
|
}
|
|
295
|
-
|
|
296
301
|
resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<number>> {
|
|
297
302
|
// code to evaluate a number
|
|
298
303
|
}
|
|
299
|
-
|
|
300
304
|
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<T>> {
|
|
301
305
|
// code to evaluate an object
|
|
302
306
|
}
|
|
303
307
|
|
|
304
308
|
status?: ProviderStatus | undefined;
|
|
305
|
-
|
|
309
|
+
|
|
310
|
+
// implement with "new OpenFeatureEventEmitter()", and use "emit()" to emit events
|
|
311
|
+
events?: ProviderEventEmitter<AnyProviderEvent> | undefined;
|
|
306
312
|
|
|
307
313
|
initialize?(context?: EvaluationContext | undefined): Promise<void> {
|
|
308
314
|
// code to initialize your provider
|
|
309
315
|
}
|
|
310
|
-
|
|
311
316
|
onClose?(): Promise<void> {
|
|
312
317
|
// code to shut down your provider
|
|
313
318
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __create = Object.create;
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
-
var __defProps = Object.defineProperties;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
7
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
9
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
10
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
-
var __spreadValues = (a, b) => {
|
|
14
|
-
for (var prop in b || (b = {}))
|
|
15
|
-
if (__hasOwnProp.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
if (__getOwnPropSymbols)
|
|
18
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
-
if (__propIsEnum.call(b, prop))
|
|
20
|
-
__defNormalProp(a, prop, b[prop]);
|
|
21
|
-
}
|
|
22
|
-
return a;
|
|
23
|
-
};
|
|
24
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
8
|
var __export = (target, all) => {
|
|
26
9
|
for (var name in all)
|
|
27
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -44,26 +27,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
44
27
|
mod
|
|
45
28
|
));
|
|
46
29
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
47
|
-
var __async = (__this, __arguments, generator) => {
|
|
48
|
-
return new Promise((resolve, reject) => {
|
|
49
|
-
var fulfilled = (value) => {
|
|
50
|
-
try {
|
|
51
|
-
step(generator.next(value));
|
|
52
|
-
} catch (e) {
|
|
53
|
-
reject(e);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
var rejected = (value) => {
|
|
57
|
-
try {
|
|
58
|
-
step(generator.throw(value));
|
|
59
|
-
} catch (e) {
|
|
60
|
-
reject(e);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
64
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
65
|
-
});
|
|
66
|
-
};
|
|
67
30
|
|
|
68
31
|
// src/index.ts
|
|
69
32
|
var src_exports = {};
|
|
@@ -86,11 +49,9 @@ var import_core7 = require("@openfeature/core");
|
|
|
86
49
|
var import_core = require("@openfeature/core");
|
|
87
50
|
var REASON_NO_OP = "No-op";
|
|
88
51
|
var NoopFeatureProvider = class {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
}
|
|
52
|
+
metadata = {
|
|
53
|
+
name: "No-op Provider"
|
|
54
|
+
};
|
|
94
55
|
get status() {
|
|
95
56
|
return import_core.ProviderStatus.NOT_READY;
|
|
96
57
|
}
|
|
@@ -121,6 +82,7 @@ var import_core3 = require("@openfeature/core");
|
|
|
121
82
|
// src/provider/in-memory-provider/variant-not-found-error.ts
|
|
122
83
|
var import_core2 = require("@openfeature/core");
|
|
123
84
|
var VariantFoundError = class extends import_core2.OpenFeatureError {
|
|
85
|
+
code;
|
|
124
86
|
constructor(message) {
|
|
125
87
|
super(message);
|
|
126
88
|
Object.setPrototypeOf(this, VariantFoundError.prototype);
|
|
@@ -131,13 +93,14 @@ var VariantFoundError = class extends import_core2.OpenFeatureError {
|
|
|
131
93
|
|
|
132
94
|
// src/provider/in-memory-provider/in-memory-provider.ts
|
|
133
95
|
var InMemoryProvider = class {
|
|
96
|
+
events = new OpenFeatureEventEmitter();
|
|
97
|
+
runsOn = "server";
|
|
98
|
+
metadata = {
|
|
99
|
+
name: "in-memory"
|
|
100
|
+
};
|
|
101
|
+
_flagConfiguration;
|
|
134
102
|
constructor(flagConfiguration = {}) {
|
|
135
|
-
this.
|
|
136
|
-
this.runsOn = "server";
|
|
137
|
-
this.metadata = {
|
|
138
|
-
name: "in-memory"
|
|
139
|
-
};
|
|
140
|
-
this._flagConfiguration = __spreadValues({}, flagConfiguration);
|
|
103
|
+
this._flagConfiguration = { ...flagConfiguration };
|
|
141
104
|
}
|
|
142
105
|
/**
|
|
143
106
|
* Overwrites the configured flags.
|
|
@@ -145,7 +108,7 @@ var InMemoryProvider = class {
|
|
|
145
108
|
*/
|
|
146
109
|
putConfiguration(flagConfiguration) {
|
|
147
110
|
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key);
|
|
148
|
-
this._flagConfiguration =
|
|
111
|
+
this._flagConfiguration = { ...flagConfiguration };
|
|
149
112
|
this.events.emit(import_core5.ServerProviderEvents.ConfigurationChanged, { flagsChanged });
|
|
150
113
|
}
|
|
151
114
|
resolveBooleanEvaluation(flagKey, defaultValue, context, logger) {
|
|
@@ -154,56 +117,49 @@ var InMemoryProvider = class {
|
|
|
154
117
|
resolveNumberEvaluation(flagKey, defaultValue, context, logger) {
|
|
155
118
|
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
156
119
|
}
|
|
157
|
-
resolveStringEvaluation(flagKey, defaultValue, context, logger) {
|
|
158
|
-
return
|
|
159
|
-
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
160
|
-
});
|
|
120
|
+
async resolveStringEvaluation(flagKey, defaultValue, context, logger) {
|
|
121
|
+
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
161
122
|
}
|
|
162
|
-
resolveObjectEvaluation(flagKey, defaultValue, context, logger) {
|
|
163
|
-
return
|
|
164
|
-
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
165
|
-
});
|
|
123
|
+
async resolveObjectEvaluation(flagKey, defaultValue, context, logger) {
|
|
124
|
+
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
166
125
|
}
|
|
167
|
-
resolveFlagWithReason(flagKey, defaultValue, ctx, logger) {
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
throw new import_core3.TypeMismatchError();
|
|
173
|
-
}
|
|
174
|
-
return resolutionResult;
|
|
175
|
-
} catch (error) {
|
|
176
|
-
if (!(error instanceof import_core3.OpenFeatureError)) {
|
|
177
|
-
throw new import_core3.GeneralError((error == null ? void 0 : error.message) || "unknown error");
|
|
178
|
-
}
|
|
179
|
-
throw error;
|
|
126
|
+
async resolveFlagWithReason(flagKey, defaultValue, ctx, logger) {
|
|
127
|
+
try {
|
|
128
|
+
const resolutionResult = this.lookupFlagValue(flagKey, defaultValue, ctx, logger);
|
|
129
|
+
if (typeof resolutionResult?.value != typeof defaultValue) {
|
|
130
|
+
throw new import_core3.TypeMismatchError();
|
|
180
131
|
}
|
|
181
|
-
|
|
132
|
+
return resolutionResult;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
if (!(error instanceof import_core3.OpenFeatureError)) {
|
|
135
|
+
throw new import_core3.GeneralError(error?.message || "unknown error");
|
|
136
|
+
}
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
182
139
|
}
|
|
183
140
|
lookupFlagValue(flagKey, defaultValue, ctx, logger) {
|
|
184
|
-
var _a;
|
|
185
141
|
if (!(flagKey in this._flagConfiguration)) {
|
|
186
142
|
const message = `no flag found with key ${flagKey}`;
|
|
187
|
-
logger
|
|
143
|
+
logger?.debug(message);
|
|
188
144
|
throw new import_core3.FlagNotFoundError(message);
|
|
189
145
|
}
|
|
190
146
|
const flagSpec = this._flagConfiguration[flagKey];
|
|
191
147
|
if (flagSpec.disabled) {
|
|
192
148
|
return { value: defaultValue, reason: import_core3.StandardResolutionReasons.DISABLED };
|
|
193
149
|
}
|
|
194
|
-
const isContextEval = ctx &&
|
|
195
|
-
const variant = isContextEval ?
|
|
196
|
-
const value = variant &&
|
|
150
|
+
const isContextEval = ctx && flagSpec?.contextEvaluator;
|
|
151
|
+
const variant = isContextEval ? flagSpec.contextEvaluator?.(ctx) : flagSpec.defaultVariant;
|
|
152
|
+
const value = variant && flagSpec?.variants[variant];
|
|
197
153
|
if (value === void 0) {
|
|
198
154
|
const message = `no value associated with variant ${variant}`;
|
|
199
|
-
logger
|
|
155
|
+
logger?.error(message);
|
|
200
156
|
throw new VariantFoundError(message);
|
|
201
157
|
}
|
|
202
|
-
return
|
|
203
|
-
value
|
|
204
|
-
|
|
158
|
+
return {
|
|
159
|
+
value,
|
|
160
|
+
...variant && { variant },
|
|
205
161
|
reason: isContextEval ? import_core3.StandardResolutionReasons.TARGETING_MATCH : import_core3.StandardResolutionReasons.STATIC
|
|
206
|
-
}
|
|
162
|
+
};
|
|
207
163
|
}
|
|
208
164
|
};
|
|
209
165
|
|
|
@@ -225,12 +181,11 @@ var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator()
|
|
|
225
181
|
var import_core4 = require("@openfeature/core");
|
|
226
182
|
var import_events = __toESM(require("events"));
|
|
227
183
|
var OpenFeatureEventEmitter = class extends import_core4.GenericEventEmitter {
|
|
184
|
+
eventEmitter = new import_events.default({ captureRejections: true });
|
|
228
185
|
constructor() {
|
|
229
186
|
super();
|
|
230
|
-
this.eventEmitter = new import_events.default({ captureRejections: true });
|
|
231
187
|
this.eventEmitter.on("error", (err) => {
|
|
232
|
-
|
|
233
|
-
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
|
|
188
|
+
this._logger?.error("Error running event handler:", err);
|
|
234
189
|
});
|
|
235
190
|
}
|
|
236
191
|
};
|
|
@@ -242,12 +197,12 @@ var import_core5 = require("@openfeature/core");
|
|
|
242
197
|
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api");
|
|
243
198
|
var _globalThis = globalThis;
|
|
244
199
|
var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI {
|
|
200
|
+
_events = new OpenFeatureEventEmitter();
|
|
201
|
+
_defaultProvider = NOOP_PROVIDER;
|
|
202
|
+
_createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
203
|
+
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
|
|
245
204
|
constructor() {
|
|
246
205
|
super("server");
|
|
247
|
-
this._events = new OpenFeatureEventEmitter();
|
|
248
|
-
this._defaultProvider = NOOP_PROVIDER;
|
|
249
|
-
this._createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
250
|
-
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
|
|
251
206
|
}
|
|
252
207
|
/**
|
|
253
208
|
* Gets a singleton instance of the OpenFeature API.
|
|
@@ -271,10 +226,9 @@ var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI {
|
|
|
271
226
|
return this._context;
|
|
272
227
|
}
|
|
273
228
|
getClient(nameOrContext, versionOrContext, contextOrUndefined) {
|
|
274
|
-
var _a, _b;
|
|
275
229
|
const name = (0, import_core6.stringOrUndefined)(nameOrContext);
|
|
276
230
|
const version = (0, import_core6.stringOrUndefined)(versionOrContext);
|
|
277
|
-
const context = (
|
|
231
|
+
const context = (0, import_core6.objectOrUndefined)(nameOrContext) ?? (0, import_core6.objectOrUndefined)(versionOrContext) ?? (0, import_core6.objectOrUndefined)(contextOrUndefined);
|
|
278
232
|
return new OpenFeatureClient(
|
|
279
233
|
() => this.getProviderForClient(name),
|
|
280
234
|
() => this.buildAndCacheEventEmitterForClient(name),
|
|
@@ -292,9 +246,9 @@ var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI {
|
|
|
292
246
|
}
|
|
293
247
|
setTransactionContextPropagator(transactionContextPropagator) {
|
|
294
248
|
const baseMessage = "Invalid TransactionContextPropagator, will not be set: ";
|
|
295
|
-
if (typeof
|
|
249
|
+
if (typeof transactionContextPropagator?.getTransactionContext !== "function") {
|
|
296
250
|
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`);
|
|
297
|
-
} else if (typeof
|
|
251
|
+
} else if (typeof transactionContextPropagator?.setTransactionContext !== "function") {
|
|
298
252
|
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`);
|
|
299
253
|
} else {
|
|
300
254
|
this._transactionContextPropagator = transactionContextPropagator;
|
|
@@ -309,8 +263,8 @@ var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI {
|
|
|
309
263
|
return this._transactionContextPropagator.getTransactionContext();
|
|
310
264
|
} catch (err) {
|
|
311
265
|
const error = err;
|
|
312
|
-
this._logger.error(`Error getting transaction context: ${error
|
|
313
|
-
this._logger.error(error
|
|
266
|
+
this._logger.error(`Error getting transaction context: ${error?.message}, returning empty context.`);
|
|
267
|
+
this._logger.error(error?.stack);
|
|
314
268
|
return {};
|
|
315
269
|
}
|
|
316
270
|
}
|
|
@@ -324,9 +278,11 @@ var OpenFeatureClient = class {
|
|
|
324
278
|
this.emitterAccessor = emitterAccessor;
|
|
325
279
|
this.globalLogger = globalLogger;
|
|
326
280
|
this.options = options;
|
|
327
|
-
this._hooks = [];
|
|
328
281
|
this._context = context;
|
|
329
282
|
}
|
|
283
|
+
_context;
|
|
284
|
+
_hooks = [];
|
|
285
|
+
_clientLogger;
|
|
330
286
|
get metadata() {
|
|
331
287
|
return {
|
|
332
288
|
name: this.options.name,
|
|
@@ -335,14 +291,13 @@ var OpenFeatureClient = class {
|
|
|
335
291
|
};
|
|
336
292
|
}
|
|
337
293
|
addHandler(eventType, handler) {
|
|
338
|
-
var _a;
|
|
339
294
|
this.emitterAccessor().addHandler(eventType, handler);
|
|
340
295
|
const shouldRunNow = (0, import_core7.statusMatchesEvent)(eventType, this._provider.status);
|
|
341
296
|
if (shouldRunNow) {
|
|
342
297
|
try {
|
|
343
298
|
handler({ clientName: this.metadata.name, providerName: this._provider.metadata.name });
|
|
344
299
|
} catch (err) {
|
|
345
|
-
|
|
300
|
+
this._logger?.error("Error running event handler:", err);
|
|
346
301
|
}
|
|
347
302
|
}
|
|
348
303
|
}
|
|
@@ -374,10 +329,8 @@ var OpenFeatureClient = class {
|
|
|
374
329
|
this._hooks = [];
|
|
375
330
|
return this;
|
|
376
331
|
}
|
|
377
|
-
getBooleanValue(flagKey, defaultValue, context, options) {
|
|
378
|
-
return
|
|
379
|
-
return (yield this.getBooleanDetails(flagKey, defaultValue, context, options)).value;
|
|
380
|
-
});
|
|
332
|
+
async getBooleanValue(flagKey, defaultValue, context, options) {
|
|
333
|
+
return (await this.getBooleanDetails(flagKey, defaultValue, context, options)).value;
|
|
381
334
|
}
|
|
382
335
|
getBooleanDetails(flagKey, defaultValue, context, options) {
|
|
383
336
|
return this.evaluate(
|
|
@@ -389,10 +342,8 @@ var OpenFeatureClient = class {
|
|
|
389
342
|
options
|
|
390
343
|
);
|
|
391
344
|
}
|
|
392
|
-
getStringValue(flagKey, defaultValue, context, options) {
|
|
393
|
-
return
|
|
394
|
-
return (yield this.getStringDetails(flagKey, defaultValue, context, options)).value;
|
|
395
|
-
});
|
|
345
|
+
async getStringValue(flagKey, defaultValue, context, options) {
|
|
346
|
+
return (await this.getStringDetails(flagKey, defaultValue, context, options)).value;
|
|
396
347
|
}
|
|
397
348
|
getStringDetails(flagKey, defaultValue, context, options) {
|
|
398
349
|
return this.evaluate(
|
|
@@ -405,10 +356,8 @@ var OpenFeatureClient = class {
|
|
|
405
356
|
options
|
|
406
357
|
);
|
|
407
358
|
}
|
|
408
|
-
getNumberValue(flagKey, defaultValue, context, options) {
|
|
409
|
-
return
|
|
410
|
-
return (yield this.getNumberDetails(flagKey, defaultValue, context, options)).value;
|
|
411
|
-
});
|
|
359
|
+
async getNumberValue(flagKey, defaultValue, context, options) {
|
|
360
|
+
return (await this.getNumberDetails(flagKey, defaultValue, context, options)).value;
|
|
412
361
|
}
|
|
413
362
|
getNumberDetails(flagKey, defaultValue, context, options) {
|
|
414
363
|
return this.evaluate(
|
|
@@ -421,109 +370,101 @@ var OpenFeatureClient = class {
|
|
|
421
370
|
options
|
|
422
371
|
);
|
|
423
372
|
}
|
|
424
|
-
getObjectValue(flagKey, defaultValue, context, options) {
|
|
425
|
-
return
|
|
426
|
-
return (yield this.getObjectDetails(flagKey, defaultValue, context, options)).value;
|
|
427
|
-
});
|
|
373
|
+
async getObjectValue(flagKey, defaultValue, context, options) {
|
|
374
|
+
return (await this.getObjectDetails(flagKey, defaultValue, context, options)).value;
|
|
428
375
|
}
|
|
429
376
|
getObjectDetails(flagKey, defaultValue, context, options) {
|
|
430
377
|
return this.evaluate(flagKey, this._provider.resolveObjectEvaluation, defaultValue, "object", context, options);
|
|
431
378
|
}
|
|
432
|
-
evaluate(
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
379
|
+
async evaluate(flagKey, resolver, defaultValue, flagType, invocationContext = {}, options = {}) {
|
|
380
|
+
const allHooks = [
|
|
381
|
+
...OpenFeature.getHooks(),
|
|
382
|
+
...this.getHooks(),
|
|
383
|
+
...options.hooks || [],
|
|
384
|
+
...this._provider.hooks || []
|
|
385
|
+
];
|
|
386
|
+
const allHooksReversed = [...allHooks].reverse();
|
|
387
|
+
const mergedContext = {
|
|
388
|
+
...OpenFeature.getContext(),
|
|
389
|
+
...OpenFeature.getTransactionContext(),
|
|
390
|
+
...this._context,
|
|
391
|
+
...invocationContext
|
|
392
|
+
};
|
|
393
|
+
const hookContext = {
|
|
394
|
+
flagKey,
|
|
395
|
+
defaultValue,
|
|
396
|
+
flagValueType: flagType,
|
|
397
|
+
clientMetadata: this.metadata,
|
|
398
|
+
providerMetadata: OpenFeature.providerMetadata,
|
|
399
|
+
context: mergedContext,
|
|
400
|
+
logger: this._logger
|
|
401
|
+
};
|
|
402
|
+
try {
|
|
403
|
+
const frozenContext = await this.beforeHooks(allHooks, hookContext, options);
|
|
404
|
+
const resolution = await resolver.call(this._provider, flagKey, defaultValue, frozenContext, this._logger);
|
|
405
|
+
const evaluationDetails = {
|
|
406
|
+
...resolution,
|
|
407
|
+
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
|
|
408
|
+
flagKey
|
|
451
409
|
};
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
reason: import_core7.StandardResolutionReasons.ERROR,
|
|
470
|
-
flagMetadata: Object.freeze({}),
|
|
471
|
-
flagKey
|
|
472
|
-
};
|
|
473
|
-
} finally {
|
|
474
|
-
yield this.finallyHooks(allHooksReversed, hookContext, options);
|
|
475
|
-
}
|
|
476
|
-
});
|
|
410
|
+
await this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
|
|
411
|
+
return evaluationDetails;
|
|
412
|
+
} catch (err) {
|
|
413
|
+
const errorMessage = err?.message;
|
|
414
|
+
const errorCode = err?.code || import_core7.ErrorCode.GENERAL;
|
|
415
|
+
await this.errorHooks(allHooksReversed, hookContext, err, options);
|
|
416
|
+
return {
|
|
417
|
+
errorCode,
|
|
418
|
+
errorMessage,
|
|
419
|
+
value: defaultValue,
|
|
420
|
+
reason: import_core7.StandardResolutionReasons.ERROR,
|
|
421
|
+
flagMetadata: Object.freeze({}),
|
|
422
|
+
flagKey
|
|
423
|
+
};
|
|
424
|
+
} finally {
|
|
425
|
+
await this.finallyHooks(allHooksReversed, hookContext, options);
|
|
426
|
+
}
|
|
477
427
|
}
|
|
478
|
-
beforeHooks(hooks, hookContext, options) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
|
|
428
|
+
async beforeHooks(hooks, hookContext, options) {
|
|
429
|
+
for (const hook of hooks) {
|
|
430
|
+
Object.freeze(hookContext);
|
|
431
|
+
Object.assign(hookContext.context, {
|
|
432
|
+
...hookContext.context,
|
|
433
|
+
...await hook?.before?.(hookContext, Object.freeze(options.hookHints))
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
return Object.freeze(hookContext.context);
|
|
487
437
|
}
|
|
488
|
-
afterHooks(hooks, hookContext, evaluationDetails, options) {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
yield (_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints);
|
|
493
|
-
}
|
|
494
|
-
});
|
|
438
|
+
async afterHooks(hooks, hookContext, evaluationDetails, options) {
|
|
439
|
+
for (const hook of hooks) {
|
|
440
|
+
await hook?.after?.(hookContext, evaluationDetails, options.hookHints);
|
|
441
|
+
}
|
|
495
442
|
}
|
|
496
|
-
errorHooks(hooks, hookContext, err, options) {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
this._logger.error(
|
|
504
|
-
if (err2 instanceof Error) {
|
|
505
|
-
this._logger.error(err2.stack);
|
|
506
|
-
}
|
|
507
|
-
this._logger.error(err2 == null ? void 0 : err2.stack);
|
|
443
|
+
async errorHooks(hooks, hookContext, err, options) {
|
|
444
|
+
for (const hook of hooks) {
|
|
445
|
+
try {
|
|
446
|
+
await hook?.error?.(hookContext, err, options.hookHints);
|
|
447
|
+
} catch (err2) {
|
|
448
|
+
this._logger.error(`Unhandled error during 'error' hook: ${err2}`);
|
|
449
|
+
if (err2 instanceof Error) {
|
|
450
|
+
this._logger.error(err2.stack);
|
|
508
451
|
}
|
|
452
|
+
this._logger.error(err2?.stack);
|
|
509
453
|
}
|
|
510
|
-
}
|
|
454
|
+
}
|
|
511
455
|
}
|
|
512
|
-
finallyHooks(hooks, hookContext, options) {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
this._logger.error(
|
|
520
|
-
if (err instanceof Error) {
|
|
521
|
-
this._logger.error(err.stack);
|
|
522
|
-
}
|
|
523
|
-
this._logger.error(err == null ? void 0 : err.stack);
|
|
456
|
+
async finallyHooks(hooks, hookContext, options) {
|
|
457
|
+
for (const hook of hooks) {
|
|
458
|
+
try {
|
|
459
|
+
await hook?.finally?.(hookContext, options.hookHints);
|
|
460
|
+
} catch (err) {
|
|
461
|
+
this._logger.error(`Unhandled error during 'finally' hook: ${err}`);
|
|
462
|
+
if (err instanceof Error) {
|
|
463
|
+
this._logger.error(err.stack);
|
|
524
464
|
}
|
|
465
|
+
this._logger.error(err?.stack);
|
|
525
466
|
}
|
|
526
|
-
}
|
|
467
|
+
}
|
|
527
468
|
}
|
|
528
469
|
get _provider() {
|
|
529
470
|
return this.providerAccessor();
|