@openfeature/server-sdk 1.13.5 → 1.15.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 +9 -3
- package/dist/cjs/index.js +365 -282
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/index.js +366 -278
- package/dist/esm/index.js.map +4 -4
- package/dist/types.d.ts +38 -59
- package/package.json +6 -6
package/dist/esm/index.js
CHANGED
|
@@ -1,36 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
var
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __async = (__this, __arguments, generator) => {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
var fulfilled = (value) => {
|
|
23
|
+
try {
|
|
24
|
+
step(generator.next(value));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
reject(e);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var rejected = (value) => {
|
|
30
|
+
try {
|
|
31
|
+
step(generator.throw(value));
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
37
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
38
|
+
});
|
|
30
39
|
};
|
|
31
|
-
|
|
32
|
-
// src/events/events.ts
|
|
33
|
-
import { ServerProviderEvents } from "@openfeature/core";
|
|
34
40
|
|
|
35
41
|
// src/provider/provider.ts
|
|
36
42
|
import { ServerProviderStatus } from "@openfeature/core";
|
|
@@ -38,9 +44,11 @@ import { ServerProviderStatus } from "@openfeature/core";
|
|
|
38
44
|
// src/provider/no-op-provider.ts
|
|
39
45
|
var REASON_NO_OP = "No-op";
|
|
40
46
|
var NoopFeatureProvider = class {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
constructor() {
|
|
48
|
+
this.metadata = {
|
|
49
|
+
name: "No-op Provider"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
44
52
|
resolveBooleanEvaluation(_, defaultValue) {
|
|
45
53
|
return this.noOp(defaultValue);
|
|
46
54
|
}
|
|
@@ -74,7 +82,6 @@ import {
|
|
|
74
82
|
// src/provider/in-memory-provider/variant-not-found-error.ts
|
|
75
83
|
import { ErrorCode, OpenFeatureError } from "@openfeature/core";
|
|
76
84
|
var VariantFoundError = class _VariantFoundError extends OpenFeatureError {
|
|
77
|
-
code;
|
|
78
85
|
constructor(message) {
|
|
79
86
|
super(message);
|
|
80
87
|
Object.setPrototypeOf(this, _VariantFoundError.prototype);
|
|
@@ -85,14 +92,13 @@ var VariantFoundError = class _VariantFoundError extends OpenFeatureError {
|
|
|
85
92
|
|
|
86
93
|
// src/provider/in-memory-provider/in-memory-provider.ts
|
|
87
94
|
var InMemoryProvider = class {
|
|
88
|
-
events = new OpenFeatureEventEmitter();
|
|
89
|
-
runsOn = "server";
|
|
90
|
-
metadata = {
|
|
91
|
-
name: "in-memory"
|
|
92
|
-
};
|
|
93
|
-
_flagConfiguration;
|
|
94
95
|
constructor(flagConfiguration = {}) {
|
|
95
|
-
this.
|
|
96
|
+
this.events = new OpenFeatureEventEmitter();
|
|
97
|
+
this.runsOn = "server";
|
|
98
|
+
this.metadata = {
|
|
99
|
+
name: "in-memory"
|
|
100
|
+
};
|
|
101
|
+
this._flagConfiguration = __spreadValues({}, flagConfiguration);
|
|
96
102
|
}
|
|
97
103
|
/**
|
|
98
104
|
* Overwrites the configured flags.
|
|
@@ -100,7 +106,7 @@ var InMemoryProvider = class {
|
|
|
100
106
|
*/
|
|
101
107
|
putConfiguration(flagConfiguration) {
|
|
102
108
|
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key);
|
|
103
|
-
this._flagConfiguration = {
|
|
109
|
+
this._flagConfiguration = __spreadValues({}, flagConfiguration);
|
|
104
110
|
this.events.emit(ServerProviderEvents.ConfigurationChanged, { flagsChanged });
|
|
105
111
|
}
|
|
106
112
|
resolveBooleanEvaluation(flagKey, defaultValue, context, logger) {
|
|
@@ -109,163 +115,77 @@ var InMemoryProvider = class {
|
|
|
109
115
|
resolveNumberEvaluation(flagKey, defaultValue, context, logger) {
|
|
110
116
|
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
111
117
|
}
|
|
112
|
-
|
|
113
|
-
return this
|
|
118
|
+
resolveStringEvaluation(flagKey, defaultValue, context, logger) {
|
|
119
|
+
return __async(this, null, function* () {
|
|
120
|
+
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
121
|
+
});
|
|
114
122
|
}
|
|
115
|
-
|
|
116
|
-
return this
|
|
123
|
+
resolveObjectEvaluation(flagKey, defaultValue, context, logger) {
|
|
124
|
+
return __async(this, null, function* () {
|
|
125
|
+
return this.resolveFlagWithReason(flagKey, defaultValue, context, logger);
|
|
126
|
+
});
|
|
117
127
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
+
resolveFlagWithReason(flagKey, defaultValue, ctx, logger) {
|
|
129
|
+
return __async(this, null, function* () {
|
|
130
|
+
try {
|
|
131
|
+
const resolutionResult = this.lookupFlagValue(flagKey, defaultValue, ctx, logger);
|
|
132
|
+
if (typeof (resolutionResult == null ? void 0 : resolutionResult.value) != typeof defaultValue) {
|
|
133
|
+
throw new TypeMismatchError();
|
|
134
|
+
}
|
|
135
|
+
return resolutionResult;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (!(error instanceof OpenFeatureError2)) {
|
|
138
|
+
throw new GeneralError((error == null ? void 0 : error.message) || "unknown error");
|
|
139
|
+
}
|
|
140
|
+
throw error;
|
|
128
141
|
}
|
|
129
|
-
|
|
130
|
-
}
|
|
142
|
+
});
|
|
131
143
|
}
|
|
132
144
|
lookupFlagValue(flagKey, defaultValue, ctx, logger) {
|
|
145
|
+
var _a;
|
|
133
146
|
if (!(flagKey in this._flagConfiguration)) {
|
|
134
147
|
const message = `no flag found with key ${flagKey}`;
|
|
135
|
-
logger
|
|
148
|
+
logger == null ? void 0 : logger.debug(message);
|
|
136
149
|
throw new FlagNotFoundError(message);
|
|
137
150
|
}
|
|
138
151
|
const flagSpec = this._flagConfiguration[flagKey];
|
|
139
152
|
if (flagSpec.disabled) {
|
|
140
153
|
return { value: defaultValue, reason: StandardResolutionReasons.DISABLED };
|
|
141
154
|
}
|
|
142
|
-
const isContextEval = ctx && flagSpec
|
|
143
|
-
const variant = isContextEval ? flagSpec.contextEvaluator
|
|
144
|
-
const value = variant && flagSpec
|
|
155
|
+
const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator);
|
|
156
|
+
const variant = isContextEval ? (_a = flagSpec.contextEvaluator) == null ? void 0 : _a.call(flagSpec, ctx) : flagSpec.defaultVariant;
|
|
157
|
+
const value = variant && (flagSpec == null ? void 0 : flagSpec.variants[variant]);
|
|
145
158
|
if (value === void 0) {
|
|
146
159
|
const message = `no value associated with variant ${variant}`;
|
|
147
|
-
logger
|
|
160
|
+
logger == null ? void 0 : logger.error(message);
|
|
148
161
|
throw new VariantFoundError(message);
|
|
149
162
|
}
|
|
150
|
-
return {
|
|
151
|
-
value
|
|
152
|
-
|
|
163
|
+
return __spreadProps(__spreadValues({
|
|
164
|
+
value
|
|
165
|
+
}, variant && { variant }), {
|
|
153
166
|
reason: isContextEval ? StandardResolutionReasons.TARGETING_MATCH : StandardResolutionReasons.STATIC
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
// src/transaction-context/no-op-transaction-context-propagator.ts
|
|
159
|
-
var NoopTransactionContextPropagator = class {
|
|
160
|
-
getTransactionContext() {
|
|
161
|
-
return {};
|
|
162
|
-
}
|
|
163
|
-
setTransactionContext(_, callback, ...args) {
|
|
164
|
-
callback(...args);
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator();
|
|
168
|
-
|
|
169
|
-
// src/transaction-context/async-local-storage-transaction-context-propagator.ts
|
|
170
|
-
import { AsyncLocalStorage } from "async_hooks";
|
|
171
|
-
var AsyncLocalStorageTransactionContextPropagator = class {
|
|
172
|
-
asyncLocalStorage = new AsyncLocalStorage();
|
|
173
|
-
getTransactionContext() {
|
|
174
|
-
return this.asyncLocalStorage.getStore() ?? {};
|
|
175
|
-
}
|
|
176
|
-
setTransactionContext(transactionContext, callback, ...args) {
|
|
177
|
-
this.asyncLocalStorage.run(transactionContext, callback, ...args);
|
|
167
|
+
});
|
|
178
168
|
}
|
|
179
169
|
};
|
|
180
170
|
|
|
181
171
|
// src/open-feature.ts
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
_domainScopedProviders = /* @__PURE__ */ new Map();
|
|
189
|
-
_createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
190
|
-
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
|
|
191
|
-
constructor() {
|
|
192
|
-
super("server");
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Gets a singleton instance of the OpenFeature API.
|
|
196
|
-
* @ignore
|
|
197
|
-
* @returns {OpenFeatureAPI} OpenFeature API
|
|
198
|
-
*/
|
|
199
|
-
static getInstance() {
|
|
200
|
-
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
|
|
201
|
-
if (globalApi) {
|
|
202
|
-
return globalApi;
|
|
203
|
-
}
|
|
204
|
-
const instance = new _OpenFeatureAPI();
|
|
205
|
-
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
|
|
206
|
-
return instance;
|
|
207
|
-
}
|
|
208
|
-
getProviderStatus(domain) {
|
|
209
|
-
if (!domain) {
|
|
210
|
-
return this._defaultProvider.status;
|
|
211
|
-
}
|
|
212
|
-
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status;
|
|
213
|
-
}
|
|
214
|
-
setContext(context) {
|
|
215
|
-
this._context = context;
|
|
216
|
-
return this;
|
|
217
|
-
}
|
|
218
|
-
getContext() {
|
|
219
|
-
return this._context;
|
|
220
|
-
}
|
|
221
|
-
getClient(domainOrContext, versionOrContext, contextOrUndefined) {
|
|
222
|
-
const domain = stringOrUndefined(domainOrContext);
|
|
223
|
-
const version = stringOrUndefined(versionOrContext);
|
|
224
|
-
const context = objectOrUndefined(domainOrContext) ?? objectOrUndefined(versionOrContext) ?? objectOrUndefined(contextOrUndefined);
|
|
225
|
-
return new OpenFeatureClient(
|
|
226
|
-
() => this.getProviderForClient(domain),
|
|
227
|
-
() => this.getProviderStatus(domain),
|
|
228
|
-
() => this.buildAndCacheEventEmitterForClient(domain),
|
|
229
|
-
() => this._logger,
|
|
230
|
-
{ domain, version },
|
|
231
|
-
context
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Clears all registered providers and resets the default provider.
|
|
236
|
-
* @returns {Promise<void>}
|
|
237
|
-
*/
|
|
238
|
-
clearProviders() {
|
|
239
|
-
return super.clearProvidersAndSetDefault(NOOP_PROVIDER);
|
|
240
|
-
}
|
|
241
|
-
setTransactionContextPropagator(transactionContextPropagator) {
|
|
242
|
-
const baseMessage = "Invalid TransactionContextPropagator, will not be set: ";
|
|
243
|
-
if (typeof transactionContextPropagator?.getTransactionContext !== "function") {
|
|
244
|
-
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`);
|
|
245
|
-
} else if (typeof transactionContextPropagator?.setTransactionContext !== "function") {
|
|
246
|
-
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`);
|
|
247
|
-
} else {
|
|
248
|
-
this._transactionContextPropagator = transactionContextPropagator;
|
|
249
|
-
}
|
|
250
|
-
return this;
|
|
251
|
-
}
|
|
252
|
-
setTransactionContext(transactionContext, callback, ...args) {
|
|
253
|
-
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args);
|
|
254
|
-
}
|
|
255
|
-
getTransactionContext() {
|
|
256
|
-
try {
|
|
257
|
-
return this._transactionContextPropagator.getTransactionContext();
|
|
258
|
-
} catch (err) {
|
|
259
|
-
const error = err;
|
|
260
|
-
this._logger.error(`Error getting transaction context: ${error?.message}, returning empty context.`);
|
|
261
|
-
this._logger.error(error?.stack);
|
|
262
|
-
return {};
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
var OpenFeature = OpenFeatureAPI.getInstance();
|
|
172
|
+
import {
|
|
173
|
+
OpenFeatureCommonAPI,
|
|
174
|
+
ProviderWrapper,
|
|
175
|
+
objectOrUndefined,
|
|
176
|
+
stringOrUndefined
|
|
177
|
+
} from "@openfeature/core";
|
|
267
178
|
|
|
268
|
-
// src/client/open-feature-client.ts
|
|
179
|
+
// src/client/internal/open-feature-client.ts
|
|
180
|
+
import {
|
|
181
|
+
ErrorCode as ErrorCode2,
|
|
182
|
+
ProviderFatalError,
|
|
183
|
+
ProviderNotReadyError,
|
|
184
|
+
SafeLogger,
|
|
185
|
+
StandardResolutionReasons as StandardResolutionReasons2,
|
|
186
|
+
instantiateErrorByErrorCode,
|
|
187
|
+
statusMatchesEvent
|
|
188
|
+
} from "@openfeature/core";
|
|
269
189
|
var OpenFeatureClient = class {
|
|
270
190
|
constructor(providerAccessor, providerStatusAccessor, emitterAccessor, globalLogger, options, context = {}) {
|
|
271
191
|
this.providerAccessor = providerAccessor;
|
|
@@ -273,16 +193,15 @@ var OpenFeatureClient = class {
|
|
|
273
193
|
this.emitterAccessor = emitterAccessor;
|
|
274
194
|
this.globalLogger = globalLogger;
|
|
275
195
|
this.options = options;
|
|
196
|
+
this._hooks = [];
|
|
276
197
|
this._context = context;
|
|
277
198
|
}
|
|
278
|
-
_context;
|
|
279
|
-
_hooks = [];
|
|
280
|
-
_clientLogger;
|
|
281
199
|
get metadata() {
|
|
200
|
+
var _a, _b;
|
|
282
201
|
return {
|
|
283
202
|
// Use domain if name is not provided
|
|
284
|
-
name: this.options.domain
|
|
285
|
-
domain: this.options.domain
|
|
203
|
+
name: (_a = this.options.domain) != null ? _a : this.options.name,
|
|
204
|
+
domain: (_b = this.options.domain) != null ? _b : this.options.name,
|
|
286
205
|
version: this.options.version,
|
|
287
206
|
providerMetadata: this.providerAccessor().metadata
|
|
288
207
|
};
|
|
@@ -291,6 +210,7 @@ var OpenFeatureClient = class {
|
|
|
291
210
|
return this.providerStatusAccessor();
|
|
292
211
|
}
|
|
293
212
|
addHandler(eventType, handler) {
|
|
213
|
+
var _a;
|
|
294
214
|
this.emitterAccessor().addHandler(eventType, handler);
|
|
295
215
|
const shouldRunNow = statusMatchesEvent(eventType, this._providerStatus);
|
|
296
216
|
if (shouldRunNow) {
|
|
@@ -301,7 +221,7 @@ var OpenFeatureClient = class {
|
|
|
301
221
|
providerName: this._provider.metadata.name
|
|
302
222
|
});
|
|
303
223
|
} catch (err) {
|
|
304
|
-
this._logger
|
|
224
|
+
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
|
|
305
225
|
}
|
|
306
226
|
}
|
|
307
227
|
}
|
|
@@ -333,8 +253,10 @@ var OpenFeatureClient = class {
|
|
|
333
253
|
this._hooks = [];
|
|
334
254
|
return this;
|
|
335
255
|
}
|
|
336
|
-
|
|
337
|
-
return (
|
|
256
|
+
getBooleanValue(flagKey, defaultValue, context, options) {
|
|
257
|
+
return __async(this, null, function* () {
|
|
258
|
+
return (yield this.getBooleanDetails(flagKey, defaultValue, context, options)).value;
|
|
259
|
+
});
|
|
338
260
|
}
|
|
339
261
|
getBooleanDetails(flagKey, defaultValue, context, options) {
|
|
340
262
|
return this.evaluate(
|
|
@@ -346,8 +268,10 @@ var OpenFeatureClient = class {
|
|
|
346
268
|
options
|
|
347
269
|
);
|
|
348
270
|
}
|
|
349
|
-
|
|
350
|
-
return (
|
|
271
|
+
getStringValue(flagKey, defaultValue, context, options) {
|
|
272
|
+
return __async(this, null, function* () {
|
|
273
|
+
return (yield this.getStringDetails(flagKey, defaultValue, context, options)).value;
|
|
274
|
+
});
|
|
351
275
|
}
|
|
352
276
|
getStringDetails(flagKey, defaultValue, context, options) {
|
|
353
277
|
return this.evaluate(
|
|
@@ -360,8 +284,10 @@ var OpenFeatureClient = class {
|
|
|
360
284
|
options
|
|
361
285
|
);
|
|
362
286
|
}
|
|
363
|
-
|
|
364
|
-
return (
|
|
287
|
+
getNumberValue(flagKey, defaultValue, context, options) {
|
|
288
|
+
return __async(this, null, function* () {
|
|
289
|
+
return (yield this.getNumberDetails(flagKey, defaultValue, context, options)).value;
|
|
290
|
+
});
|
|
365
291
|
}
|
|
366
292
|
getNumberDetails(flagKey, defaultValue, context, options) {
|
|
367
293
|
return this.evaluate(
|
|
@@ -374,106 +300,117 @@ var OpenFeatureClient = class {
|
|
|
374
300
|
options
|
|
375
301
|
);
|
|
376
302
|
}
|
|
377
|
-
|
|
378
|
-
return (
|
|
303
|
+
getObjectValue(flagKey, defaultValue, context, options) {
|
|
304
|
+
return __async(this, null, function* () {
|
|
305
|
+
return (yield this.getObjectDetails(flagKey, defaultValue, context, options)).value;
|
|
306
|
+
});
|
|
379
307
|
}
|
|
380
308
|
getObjectDetails(flagKey, defaultValue, context, options) {
|
|
381
309
|
return this.evaluate(flagKey, this._provider.resolveObjectEvaluation, defaultValue, "object", context, options);
|
|
382
310
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
...
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
providerMetadata: this._provider.metadata,
|
|
403
|
-
context: mergedContext,
|
|
404
|
-
logger: this._logger
|
|
405
|
-
};
|
|
406
|
-
try {
|
|
407
|
-
const frozenContext = await this.beforeHooks(allHooks, hookContext, options);
|
|
408
|
-
if (this.providerStatus === ServerProviderStatus.NOT_READY) {
|
|
409
|
-
throw new ProviderNotReadyError("provider has not yet initialized");
|
|
410
|
-
} else if (this.providerStatus === ServerProviderStatus.FATAL) {
|
|
411
|
-
throw new ProviderFatalError("provider is in an irrecoverable error state");
|
|
412
|
-
}
|
|
413
|
-
const resolution = await resolver.call(this._provider, flagKey, defaultValue, frozenContext, this._logger);
|
|
414
|
-
const evaluationDetails = {
|
|
415
|
-
...resolution,
|
|
416
|
-
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}),
|
|
417
|
-
flagKey
|
|
418
|
-
};
|
|
419
|
-
await this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
|
|
420
|
-
return evaluationDetails;
|
|
421
|
-
} catch (err) {
|
|
422
|
-
const errorMessage = err?.message;
|
|
423
|
-
const errorCode = err?.code || ErrorCode2.GENERAL;
|
|
424
|
-
await this.errorHooks(allHooksReversed, hookContext, err, options);
|
|
425
|
-
return {
|
|
426
|
-
errorCode,
|
|
427
|
-
errorMessage,
|
|
428
|
-
value: defaultValue,
|
|
429
|
-
reason: StandardResolutionReasons2.ERROR,
|
|
430
|
-
flagMetadata: Object.freeze({}),
|
|
431
|
-
flagKey
|
|
311
|
+
evaluate(_0, _1, _2, _3) {
|
|
312
|
+
return __async(this, arguments, function* (flagKey, resolver, defaultValue, flagType, invocationContext = {}, options = {}) {
|
|
313
|
+
var _a;
|
|
314
|
+
const allHooks = [
|
|
315
|
+
...OpenFeature.getHooks(),
|
|
316
|
+
...this.getHooks(),
|
|
317
|
+
...options.hooks || [],
|
|
318
|
+
...this._provider.hooks || []
|
|
319
|
+
];
|
|
320
|
+
const allHooksReversed = [...allHooks].reverse();
|
|
321
|
+
const mergedContext = __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, OpenFeature.getContext()), OpenFeature.getTransactionContext()), this._context), invocationContext);
|
|
322
|
+
const hookContext = {
|
|
323
|
+
flagKey,
|
|
324
|
+
defaultValue,
|
|
325
|
+
flagValueType: flagType,
|
|
326
|
+
clientMetadata: this.metadata,
|
|
327
|
+
providerMetadata: this._provider.metadata,
|
|
328
|
+
context: mergedContext,
|
|
329
|
+
logger: this._logger
|
|
432
330
|
};
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
331
|
+
try {
|
|
332
|
+
const frozenContext = yield this.beforeHooks(allHooks, hookContext, options);
|
|
333
|
+
if (this.providerStatus === ServerProviderStatus.NOT_READY) {
|
|
334
|
+
throw new ProviderNotReadyError("provider has not yet initialized");
|
|
335
|
+
} else if (this.providerStatus === ServerProviderStatus.FATAL) {
|
|
336
|
+
throw new ProviderFatalError("provider is in an irrecoverable error state");
|
|
337
|
+
}
|
|
338
|
+
const resolution = yield resolver.call(this._provider, flagKey, defaultValue, frozenContext, this._logger);
|
|
339
|
+
const evaluationDetails = __spreadProps(__spreadValues({}, resolution), {
|
|
340
|
+
flagMetadata: Object.freeze((_a = resolution.flagMetadata) != null ? _a : {}),
|
|
341
|
+
flagKey
|
|
342
|
+
});
|
|
343
|
+
if (evaluationDetails.errorCode) {
|
|
344
|
+
throw instantiateErrorByErrorCode(evaluationDetails.errorCode);
|
|
345
|
+
}
|
|
346
|
+
yield this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options);
|
|
347
|
+
return evaluationDetails;
|
|
348
|
+
} catch (err) {
|
|
349
|
+
const errorMessage = err == null ? void 0 : err.message;
|
|
350
|
+
const errorCode = (err == null ? void 0 : err.code) || ErrorCode2.GENERAL;
|
|
351
|
+
yield this.errorHooks(allHooksReversed, hookContext, err, options);
|
|
352
|
+
return {
|
|
353
|
+
errorCode,
|
|
354
|
+
errorMessage,
|
|
355
|
+
value: defaultValue,
|
|
356
|
+
reason: StandardResolutionReasons2.ERROR,
|
|
357
|
+
flagMetadata: Object.freeze({}),
|
|
358
|
+
flagKey
|
|
359
|
+
};
|
|
360
|
+
} finally {
|
|
361
|
+
yield this.finallyHooks(allHooksReversed, hookContext, options);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
436
364
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
|
|
365
|
+
beforeHooks(hooks, hookContext, options) {
|
|
366
|
+
return __async(this, null, function* () {
|
|
367
|
+
var _a;
|
|
368
|
+
for (const hook of hooks) {
|
|
369
|
+
Object.freeze(hookContext);
|
|
370
|
+
Object.assign(hookContext.context, __spreadValues(__spreadValues({}, hookContext.context), yield (_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(options.hookHints))));
|
|
371
|
+
}
|
|
372
|
+
return Object.freeze(hookContext.context);
|
|
373
|
+
});
|
|
446
374
|
}
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
375
|
+
afterHooks(hooks, hookContext, evaluationDetails, options) {
|
|
376
|
+
return __async(this, null, function* () {
|
|
377
|
+
var _a;
|
|
378
|
+
for (const hook of hooks) {
|
|
379
|
+
yield (_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
451
382
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
this._logger.error(err2
|
|
383
|
+
errorHooks(hooks, hookContext, err, options) {
|
|
384
|
+
return __async(this, null, function* () {
|
|
385
|
+
var _a;
|
|
386
|
+
for (const hook of hooks) {
|
|
387
|
+
try {
|
|
388
|
+
yield (_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, options.hookHints);
|
|
389
|
+
} catch (err2) {
|
|
390
|
+
this._logger.error(`Unhandled error during 'error' hook: ${err2}`);
|
|
391
|
+
if (err2 instanceof Error) {
|
|
392
|
+
this._logger.error(err2.stack);
|
|
393
|
+
}
|
|
394
|
+
this._logger.error(err2 == null ? void 0 : err2.stack);
|
|
460
395
|
}
|
|
461
|
-
this._logger.error(err2?.stack);
|
|
462
396
|
}
|
|
463
|
-
}
|
|
397
|
+
});
|
|
464
398
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this._logger.error(err
|
|
399
|
+
finallyHooks(hooks, hookContext, options) {
|
|
400
|
+
return __async(this, null, function* () {
|
|
401
|
+
var _a;
|
|
402
|
+
for (const hook of hooks) {
|
|
403
|
+
try {
|
|
404
|
+
yield (_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, options.hookHints);
|
|
405
|
+
} catch (err) {
|
|
406
|
+
this._logger.error(`Unhandled error during 'finally' hook: ${err}`);
|
|
407
|
+
if (err instanceof Error) {
|
|
408
|
+
this._logger.error(err.stack);
|
|
409
|
+
}
|
|
410
|
+
this._logger.error(err == null ? void 0 : err.stack);
|
|
473
411
|
}
|
|
474
|
-
this._logger.error(err?.stack);
|
|
475
412
|
}
|
|
476
|
-
}
|
|
413
|
+
});
|
|
477
414
|
}
|
|
478
415
|
get _provider() {
|
|
479
416
|
return this.providerAccessor();
|
|
@@ -486,6 +423,158 @@ var OpenFeatureClient = class {
|
|
|
486
423
|
}
|
|
487
424
|
};
|
|
488
425
|
|
|
426
|
+
// src/events/open-feature-event-emitter.ts
|
|
427
|
+
import { GenericEventEmitter } from "@openfeature/core";
|
|
428
|
+
import { EventEmitter } from "events";
|
|
429
|
+
var OpenFeatureEventEmitter = class extends GenericEventEmitter {
|
|
430
|
+
constructor() {
|
|
431
|
+
super();
|
|
432
|
+
this.eventEmitter = new EventEmitter({ captureRejections: true });
|
|
433
|
+
this.eventEmitter.on("error", (err) => {
|
|
434
|
+
var _a;
|
|
435
|
+
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err);
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
// src/events/events.ts
|
|
441
|
+
import { ServerProviderEvents } from "@openfeature/core";
|
|
442
|
+
|
|
443
|
+
// src/transaction-context/no-op-transaction-context-propagator.ts
|
|
444
|
+
var NoopTransactionContextPropagator = class {
|
|
445
|
+
getTransactionContext() {
|
|
446
|
+
return {};
|
|
447
|
+
}
|
|
448
|
+
setTransactionContext(_, callback, ...args) {
|
|
449
|
+
callback(...args);
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator();
|
|
453
|
+
|
|
454
|
+
// src/transaction-context/async-local-storage-transaction-context-propagator.ts
|
|
455
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
456
|
+
var AsyncLocalStorageTransactionContextPropagator = class {
|
|
457
|
+
constructor() {
|
|
458
|
+
this.asyncLocalStorage = new AsyncLocalStorage();
|
|
459
|
+
}
|
|
460
|
+
getTransactionContext() {
|
|
461
|
+
var _a;
|
|
462
|
+
return (_a = this.asyncLocalStorage.getStore()) != null ? _a : {};
|
|
463
|
+
}
|
|
464
|
+
setTransactionContext(transactionContext, callback, ...args) {
|
|
465
|
+
this.asyncLocalStorage.run(transactionContext, callback, ...args);
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
// src/open-feature.ts
|
|
470
|
+
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api");
|
|
471
|
+
var _globalThis = globalThis;
|
|
472
|
+
var OpenFeatureAPI = class _OpenFeatureAPI extends OpenFeatureCommonAPI {
|
|
473
|
+
constructor() {
|
|
474
|
+
super("server");
|
|
475
|
+
this._statusEnumType = ServerProviderStatus;
|
|
476
|
+
this._apiEmitter = new OpenFeatureEventEmitter();
|
|
477
|
+
this._defaultProvider = new ProviderWrapper(
|
|
478
|
+
NOOP_PROVIDER,
|
|
479
|
+
ServerProviderStatus.NOT_READY,
|
|
480
|
+
this._statusEnumType
|
|
481
|
+
);
|
|
482
|
+
this._domainScopedProviders = /* @__PURE__ */ new Map();
|
|
483
|
+
this._createEventEmitter = () => new OpenFeatureEventEmitter();
|
|
484
|
+
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Gets a singleton instance of the OpenFeature API.
|
|
488
|
+
* @ignore
|
|
489
|
+
* @returns {OpenFeatureAPI} OpenFeature API
|
|
490
|
+
*/
|
|
491
|
+
static getInstance() {
|
|
492
|
+
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY];
|
|
493
|
+
if (globalApi) {
|
|
494
|
+
return globalApi;
|
|
495
|
+
}
|
|
496
|
+
const instance = new _OpenFeatureAPI();
|
|
497
|
+
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance;
|
|
498
|
+
return instance;
|
|
499
|
+
}
|
|
500
|
+
getProviderStatus(domain) {
|
|
501
|
+
var _a, _b;
|
|
502
|
+
if (!domain) {
|
|
503
|
+
return this._defaultProvider.status;
|
|
504
|
+
}
|
|
505
|
+
return (_b = (_a = this._domainScopedProviders.get(domain)) == null ? void 0 : _a.status) != null ? _b : this._defaultProvider.status;
|
|
506
|
+
}
|
|
507
|
+
setProviderAndWait(domainOrProvider, providerOrUndefined) {
|
|
508
|
+
return __async(this, null, function* () {
|
|
509
|
+
const domain = stringOrUndefined(domainOrProvider);
|
|
510
|
+
const provider = domain ? objectOrUndefined(providerOrUndefined) : objectOrUndefined(domainOrProvider);
|
|
511
|
+
yield this.setAwaitableProvider(domain, provider);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
setProvider(clientOrProvider, providerOrUndefined) {
|
|
515
|
+
const domain = stringOrUndefined(clientOrProvider);
|
|
516
|
+
const provider = domain ? objectOrUndefined(providerOrUndefined) : objectOrUndefined(clientOrProvider);
|
|
517
|
+
const maybePromise = this.setAwaitableProvider(domain, provider);
|
|
518
|
+
Promise.resolve(maybePromise).catch((err) => {
|
|
519
|
+
this._logger.error("Error during provider initialization:", err);
|
|
520
|
+
});
|
|
521
|
+
return this;
|
|
522
|
+
}
|
|
523
|
+
setContext(context) {
|
|
524
|
+
this._context = context;
|
|
525
|
+
return this;
|
|
526
|
+
}
|
|
527
|
+
getContext() {
|
|
528
|
+
return this._context;
|
|
529
|
+
}
|
|
530
|
+
getClient(domainOrContext, versionOrContext, contextOrUndefined) {
|
|
531
|
+
var _a, _b;
|
|
532
|
+
const domain = stringOrUndefined(domainOrContext);
|
|
533
|
+
const version = stringOrUndefined(versionOrContext);
|
|
534
|
+
const context = (_b = (_a = objectOrUndefined(domainOrContext)) != null ? _a : objectOrUndefined(versionOrContext)) != null ? _b : objectOrUndefined(contextOrUndefined);
|
|
535
|
+
return new OpenFeatureClient(
|
|
536
|
+
() => this.getProviderForClient(domain),
|
|
537
|
+
() => this.getProviderStatus(domain),
|
|
538
|
+
() => this.buildAndCacheEventEmitterForClient(domain),
|
|
539
|
+
() => this._logger,
|
|
540
|
+
{ domain, version },
|
|
541
|
+
context
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Clears all registered providers and resets the default provider.
|
|
546
|
+
* @returns {Promise<void>}
|
|
547
|
+
*/
|
|
548
|
+
clearProviders() {
|
|
549
|
+
return super.clearProvidersAndSetDefault(NOOP_PROVIDER);
|
|
550
|
+
}
|
|
551
|
+
setTransactionContextPropagator(transactionContextPropagator) {
|
|
552
|
+
const baseMessage = "Invalid TransactionContextPropagator, will not be set: ";
|
|
553
|
+
if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") {
|
|
554
|
+
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`);
|
|
555
|
+
} else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") {
|
|
556
|
+
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`);
|
|
557
|
+
} else {
|
|
558
|
+
this._transactionContextPropagator = transactionContextPropagator;
|
|
559
|
+
}
|
|
560
|
+
return this;
|
|
561
|
+
}
|
|
562
|
+
setTransactionContext(transactionContext, callback, ...args) {
|
|
563
|
+
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args);
|
|
564
|
+
}
|
|
565
|
+
getTransactionContext() {
|
|
566
|
+
try {
|
|
567
|
+
return this._transactionContextPropagator.getTransactionContext();
|
|
568
|
+
} catch (err) {
|
|
569
|
+
const error = err;
|
|
570
|
+
this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`);
|
|
571
|
+
this._logger.error(error == null ? void 0 : error.stack);
|
|
572
|
+
return {};
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
var OpenFeature = OpenFeatureAPI.getInstance();
|
|
577
|
+
|
|
489
578
|
// src/index.ts
|
|
490
579
|
export * from "@openfeature/core";
|
|
491
580
|
export {
|
|
@@ -495,7 +584,6 @@ export {
|
|
|
495
584
|
NOOP_TRANSACTION_CONTEXT_PROPAGATOR,
|
|
496
585
|
OpenFeature,
|
|
497
586
|
OpenFeatureAPI,
|
|
498
|
-
OpenFeatureClient,
|
|
499
587
|
OpenFeatureEventEmitter,
|
|
500
588
|
ServerProviderEvents as ProviderEvents,
|
|
501
589
|
ServerProviderStatus as ProviderStatus
|