@openfeature/web-sdk
Advanced tools
Comparing version 0.4.10 to 0.4.11
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __defProps = Object.defineProperties; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropDescs = Object.getOwnPropertyDescriptors; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __reflectGet = Reflect.get; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __spreadValues = (a, b) => { | ||
for (var prop in b || (b = {})) | ||
if (__hasOwnProp.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
if (__getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(b)) { | ||
if (__propIsEnum.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
} | ||
return a; | ||
}; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __commonJS = (cb, mod) => function __require() { | ||
@@ -51,23 +33,2 @@ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj); | ||
var __async = (__this, __arguments, generator) => { | ||
return new Promise((resolve, reject) => { | ||
var fulfilled = (value) => { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var rejected = (value) => { | ||
try { | ||
step(generator.throw(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); | ||
step((generator = generator.apply(__this, __arguments)).next()); | ||
}); | ||
}; | ||
@@ -469,8 +430,7 @@ // ../../node_modules/events/events.js | ||
var OpenFeatureEventEmitter = class extends import_core.GenericEventEmitter { | ||
eventEmitter = new import_events.default({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter = new import_events.default({ captureRejections: true }); | ||
this.eventEmitter.on("error", (err) => { | ||
var _a; | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
@@ -487,7 +447,5 @@ } | ||
var NoopFeatureProvider = class { | ||
constructor() { | ||
this.metadata = { | ||
name: "No-op Provider" | ||
}; | ||
} | ||
metadata = { | ||
name: "No-op Provider" | ||
}; | ||
get status() { | ||
@@ -523,2 +481,3 @@ return import_core3.ProviderStatus.NOT_READY; | ||
var VariantNotFoundError = class extends import_core4.OpenFeatureError { | ||
code; | ||
constructor(message) { | ||
@@ -534,24 +493,24 @@ super(message); | ||
var InMemoryProvider = class { | ||
events = new OpenFeatureEventEmitter(); | ||
runsOn = "client"; | ||
status = import_core5.ProviderStatus.NOT_READY; | ||
metadata = { | ||
name: "in-memory" | ||
}; | ||
_flagConfiguration; | ||
_context; | ||
constructor(flagConfiguration = {}) { | ||
this.events = new OpenFeatureEventEmitter(); | ||
this.runsOn = "client"; | ||
this.status = import_core5.ProviderStatus.NOT_READY; | ||
this.metadata = { | ||
name: "in-memory" | ||
}; | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this._flagConfiguration = { ...flagConfiguration }; | ||
} | ||
initialize(context) { | ||
return __async(this, null, function* () { | ||
try { | ||
for (const key in this._flagConfiguration) { | ||
this.resolveFlagWithReason(key, context); | ||
} | ||
this._context = context; | ||
this.status = import_core5.ProviderStatus.READY; | ||
} catch (error) { | ||
this.status = import_core5.ProviderStatus.ERROR; | ||
throw error; | ||
async initialize(context) { | ||
try { | ||
for (const key in this._flagConfiguration) { | ||
this.resolveFlagWithReason(key, context); | ||
} | ||
}); | ||
this._context = context; | ||
this.status = import_core5.ProviderStatus.READY; | ||
} catch (error) { | ||
this.status = import_core5.ProviderStatus.ERROR; | ||
throw error; | ||
} | ||
} | ||
@@ -562,17 +521,15 @@ /** | ||
*/ | ||
putConfiguration(flagConfiguration) { | ||
return __async(this, null, function* () { | ||
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key); | ||
this.status = import_core5.ProviderStatus.STALE; | ||
this.events.emit(import_core2.ClientProviderEvents.Stale); | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this.events.emit(import_core2.ClientProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
try { | ||
yield this.initialize(this._context); | ||
this.events.emit(import_core2.ClientProviderEvents.Ready); | ||
} catch (err) { | ||
this.events.emit(import_core2.ClientProviderEvents.Error); | ||
throw err; | ||
} | ||
}); | ||
async putConfiguration(flagConfiguration) { | ||
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key); | ||
this.status = import_core5.ProviderStatus.STALE; | ||
this.events.emit(import_core2.ClientProviderEvents.Stale); | ||
this._flagConfiguration = { ...flagConfiguration }; | ||
this.events.emit(import_core2.ClientProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
try { | ||
await this.initialize(this._context); | ||
this.events.emit(import_core2.ClientProviderEvents.Ready); | ||
} catch (err) { | ||
this.events.emit(import_core2.ClientProviderEvents.Error); | ||
throw err; | ||
} | ||
} | ||
@@ -594,3 +551,3 @@ resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { | ||
const message = `no flag found with key ${flagKey}`; | ||
logger == null ? void 0 : logger.debug(message); | ||
logger?.debug(message); | ||
throw new import_core5.FlagNotFoundError(message); | ||
@@ -604,3 +561,3 @@ } | ||
const message = `no value associated with variant provided for ${flagKey} found`; | ||
logger == null ? void 0 : logger.error(message); | ||
logger?.error(message); | ||
throw new VariantNotFoundError(message); | ||
@@ -619,3 +576,3 @@ } | ||
if (!(error instanceof import_core5.OpenFeatureError)) { | ||
throw new import_core5.GeneralError((error == null ? void 0 : error.message) || "unknown error"); | ||
throw new import_core5.GeneralError(error?.message || "unknown error"); | ||
} | ||
@@ -626,14 +583,13 @@ throw error; | ||
lookupFlagValue(flagKey, ctx) { | ||
var _a; | ||
const flagSpec = this._flagConfiguration[flagKey]; | ||
const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator); | ||
const variant = isContextEval ? (_a = flagSpec.contextEvaluator) == null ? void 0 : _a.call(flagSpec, ctx) : flagSpec.defaultVariant; | ||
const value = variant && (flagSpec == null ? void 0 : flagSpec.variants[variant]); | ||
const isContextEval = ctx && flagSpec?.contextEvaluator; | ||
const variant = isContextEval ? flagSpec.contextEvaluator?.(ctx) : flagSpec.defaultVariant; | ||
const value = variant && flagSpec?.variants[variant]; | ||
const evalReason = isContextEval ? import_core5.StandardResolutionReasons.TARGETING_MATCH : import_core5.StandardResolutionReasons.STATIC; | ||
const reason = this.status === import_core5.ProviderStatus.STALE ? import_core5.StandardResolutionReasons.CACHED : evalReason; | ||
return __spreadProps(__spreadValues({ | ||
value | ||
}, variant && { variant }), { | ||
return { | ||
value, | ||
...variant && { variant }, | ||
reason | ||
}); | ||
}; | ||
} | ||
@@ -646,8 +602,8 @@ }; | ||
var OpenFeatureAPI = class extends import_core6.OpenFeatureCommonAPI { | ||
_events = new OpenFeatureEventEmitter(); | ||
_defaultProvider = NOOP_PROVIDER; | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_namedProviderContext = /* @__PURE__ */ new Map(); | ||
constructor() { | ||
super("client"); | ||
this._events = new OpenFeatureEventEmitter(); | ||
this._defaultProvider = NOOP_PROVIDER; | ||
this._createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
this._namedProviderContext = /* @__PURE__ */ new Map(); | ||
} | ||
@@ -668,35 +624,32 @@ /** | ||
} | ||
setContext(nameOrContext, contextOrUndefined) { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
const clientName = (0, import_core6.stringOrUndefined)(nameOrContext); | ||
const context = (_b = (_a = (0, import_core6.objectOrUndefined)(nameOrContext)) != null ? _a : (0, import_core6.objectOrUndefined)(contextOrUndefined)) != null ? _b : {}; | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.set(clientName, context); | ||
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, context); | ||
} else { | ||
this._namedProviderContext.set(clientName, context); | ||
} | ||
async setContext(nameOrContext, contextOrUndefined) { | ||
const clientName = (0, import_core6.stringOrUndefined)(nameOrContext); | ||
const context = (0, import_core6.objectOrUndefined)(nameOrContext) ?? (0, import_core6.objectOrUndefined)(contextOrUndefined) ?? {}; | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.set(clientName, context); | ||
await this.runProviderContextChangeHandler(clientName, provider, oldContext, context); | ||
} else { | ||
const oldContext = this._context; | ||
this._context = context; | ||
const defaultContextNameProviders = Array.from(this._clientProviders.entries()).filter(([name]) => !this._namedProviderContext.has(name)).reduce((acc, [name, provider]) => { | ||
acc.push({ name, provider }); | ||
return acc; | ||
}, []); | ||
const allProviders = [ | ||
// add in the default (no name) | ||
{ name: void 0, provider: this._defaultProvider }, | ||
...defaultContextNameProviders | ||
]; | ||
yield Promise.all( | ||
allProviders.map( | ||
(tuple) => this.runProviderContextChangeHandler(tuple.name, tuple.provider, oldContext, context) | ||
) | ||
); | ||
this._namedProviderContext.set(clientName, context); | ||
} | ||
}); | ||
} else { | ||
const oldContext = this._context; | ||
this._context = context; | ||
const defaultContextNameProviders = Array.from(this._clientProviders.entries()).filter(([name]) => !this._namedProviderContext.has(name)).reduce((acc, [name, provider]) => { | ||
acc.push({ name, provider }); | ||
return acc; | ||
}, []); | ||
const allProviders = [ | ||
// add in the default (no name) | ||
{ name: void 0, provider: this._defaultProvider }, | ||
...defaultContextNameProviders | ||
]; | ||
await Promise.all( | ||
allProviders.map( | ||
(tuple) => this.runProviderContextChangeHandler(tuple.name, tuple.provider, oldContext, context) | ||
) | ||
); | ||
} | ||
} | ||
@@ -715,19 +668,17 @@ getContext(nameOrUndefined) { | ||
} | ||
clearContext(nameOrUndefined) { | ||
return __async(this, null, function* () { | ||
const clientName = (0, import_core6.stringOrUndefined)(nameOrUndefined); | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.delete(clientName); | ||
const newContext = this.getContext(); | ||
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, newContext); | ||
} else { | ||
this._namedProviderContext.delete(clientName); | ||
} | ||
async clearContext(nameOrUndefined) { | ||
const clientName = (0, import_core6.stringOrUndefined)(nameOrUndefined); | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.delete(clientName); | ||
const newContext = this.getContext(); | ||
await this.runProviderContextChangeHandler(clientName, provider, oldContext, newContext); | ||
} else { | ||
return this.setContext({}); | ||
this._namedProviderContext.delete(clientName); | ||
} | ||
}); | ||
} else { | ||
return this.setContext({}); | ||
} | ||
} | ||
@@ -738,7 +689,5 @@ /** | ||
*/ | ||
clearContexts() { | ||
return __async(this, null, function* () { | ||
yield this.clearContext(); | ||
yield Promise.allSettled(Array.from(this._clientProviders.keys()).map((name) => this.clearContext(name))); | ||
}); | ||
async clearContexts() { | ||
await this.clearContext(); | ||
await Promise.allSettled(Array.from(this._clientProviders.keys()).map((name) => this.clearContext(name))); | ||
} | ||
@@ -770,28 +719,23 @@ /** | ||
*/ | ||
clearProviders() { | ||
return __async(this, null, function* () { | ||
yield __superGet(OpenFeatureAPI.prototype, this, "clearProvidersAndSetDefault").call(this, NOOP_PROVIDER); | ||
this._namedProviderContext.clear(); | ||
}); | ||
async clearProviders() { | ||
await super.clearProvidersAndSetDefault(NOOP_PROVIDER); | ||
this._namedProviderContext.clear(); | ||
} | ||
runProviderContextChangeHandler(clientName, provider, oldContext, newContext) { | ||
return __async(this, null, function* () { | ||
var _a, _b, _c, _d, _e; | ||
const providerName = provider.metadata.name; | ||
try { | ||
yield (_a = provider.onContextChange) == null ? void 0 : _a.call(provider, oldContext, newContext); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
}); | ||
(_b = this._events) == null ? void 0 : _b.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
} catch (err) { | ||
const error = err; | ||
const message = `Error running ${(_c = provider == null ? void 0 : provider.metadata) == null ? void 0 : _c.name}'s context change handler: ${error == null ? void 0 : error.message}`; | ||
(_d = this._logger) == null ? void 0 : _d.error(`${message}`, err); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message }); | ||
}); | ||
(_e = this._events) == null ? void 0 : _e.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message }); | ||
} | ||
}); | ||
async runProviderContextChangeHandler(clientName, provider, oldContext, newContext) { | ||
const providerName = provider.metadata.name; | ||
try { | ||
await provider.onContextChange?.(oldContext, newContext); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter?.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
}); | ||
this._events?.emit(import_core2.ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
} catch (err) { | ||
const error = err; | ||
const message = `Error running ${provider?.metadata?.name}'s context change handler: ${error?.message}`; | ||
this._logger?.error(`${message}`, err); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter?.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message }); | ||
}); | ||
this._events?.emit(import_core2.ClientProviderEvents.Error, { clientName, providerName, message }); | ||
} | ||
} | ||
@@ -808,4 +752,5 @@ }; | ||
this.options = options; | ||
this._hooks = []; | ||
} | ||
_hooks = []; | ||
_clientLogger; | ||
get metadata() { | ||
@@ -819,7 +764,5 @@ return { | ||
get providerStatus() { | ||
var _a; | ||
return ((_a = this.providerAccessor()) == null ? void 0 : _a.status) || import_core7.ProviderStatus.READY; | ||
return this.providerAccessor()?.status || import_core7.ProviderStatus.READY; | ||
} | ||
addHandler(eventType, handler) { | ||
var _a; | ||
this.emitterAccessor().addHandler(eventType, handler); | ||
@@ -831,3 +774,3 @@ const shouldRunNow = (0, import_core7.statusMatchesEvent)(eventType, this._provider.status); | ||
} catch (err) { | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
this._logger?.error("Error running event handler:", err); | ||
} | ||
@@ -896,3 +839,2 @@ } | ||
evaluate(flagKey, resolver, defaultValue, flagType, options = {}) { | ||
var _a, _b; | ||
const allHooks = [ | ||
@@ -905,3 +847,5 @@ ...OpenFeature.getHooks(), | ||
const allHooksReversed = [...allHooks].reverse(); | ||
const context = __spreadValues({}, OpenFeature.getContext((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.name)); | ||
const context = { | ||
...OpenFeature.getContext(this?.options?.name) | ||
}; | ||
const hookContext = { | ||
@@ -919,11 +863,12 @@ flagKey, | ||
const resolution = resolver.call(this._provider, flagKey, defaultValue, context, this._logger); | ||
const evaluationDetails = __spreadProps(__spreadValues({}, resolution), { | ||
flagMetadata: Object.freeze((_b = resolution.flagMetadata) != null ? _b : {}), | ||
const evaluationDetails = { | ||
...resolution, | ||
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}), | ||
flagKey | ||
}); | ||
}; | ||
this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options); | ||
return evaluationDetails; | ||
} catch (err) { | ||
const errorMessage = err == null ? void 0 : err.message; | ||
const errorCode = (err == null ? void 0 : err.code) || import_core7.ErrorCode.GENERAL; | ||
const errorMessage = err?.message; | ||
const errorCode = err?.code || import_core7.ErrorCode.GENERAL; | ||
this.errorHooks(allHooksReversed, hookContext, err, options); | ||
@@ -943,20 +888,17 @@ return { | ||
beforeHooks(hooks, hookContext, options) { | ||
var _a; | ||
Object.freeze(hookContext); | ||
Object.freeze(hookContext.context); | ||
for (const hook of hooks) { | ||
(_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(options.hookHints)); | ||
hook?.before?.(hookContext, Object.freeze(options.hookHints)); | ||
} | ||
} | ||
afterHooks(hooks, hookContext, evaluationDetails, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
(_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints); | ||
hook?.after?.(hookContext, evaluationDetails, options.hookHints); | ||
} | ||
} | ||
errorHooks(hooks, hookContext, err, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
try { | ||
(_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, options.hookHints); | ||
hook?.error?.(hookContext, err, options.hookHints); | ||
} catch (err2) { | ||
@@ -967,3 +909,3 @@ this._logger.error(`Unhandled error during 'error' hook: ${err2}`); | ||
} | ||
this._logger.error(err2 == null ? void 0 : err2.stack); | ||
this._logger.error(err2?.stack); | ||
} | ||
@@ -973,6 +915,5 @@ } | ||
finallyHooks(hooks, hookContext, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
try { | ||
(_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, options.hookHints); | ||
hook?.finally?.(hookContext, options.hookHints); | ||
} catch (err) { | ||
@@ -983,3 +924,3 @@ this._logger.error(`Unhandled error during 'finally' hook: ${err}`); | ||
} | ||
this._logger.error(err == null ? void 0 : err.stack); | ||
this._logger.error(err?.stack); | ||
} | ||
@@ -986,0 +927,0 @@ } |
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
var __defProps = Object.defineProperties; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropDescs = Object.getOwnPropertyDescriptors; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
var __reflectGet = Reflect.get; | ||
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; | ||
var __spreadValues = (a, b) => { | ||
for (var prop in b || (b = {})) | ||
if (__hasOwnProp.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
if (__getOwnPropSymbols) | ||
for (var prop of __getOwnPropSymbols(b)) { | ||
if (__propIsEnum.call(b, prop)) | ||
__defNormalProp(a, prop, b[prop]); | ||
} | ||
return a; | ||
}; | ||
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); | ||
var __commonJS = (cb, mod) => function __require() { | ||
@@ -44,23 +26,2 @@ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; | ||
)); | ||
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj); | ||
var __async = (__this, __arguments, generator) => { | ||
return new Promise((resolve, reject) => { | ||
var fulfilled = (value) => { | ||
try { | ||
step(generator.next(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var rejected = (value) => { | ||
try { | ||
step(generator.throw(value)); | ||
} catch (e) { | ||
reject(e); | ||
} | ||
}; | ||
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); | ||
step((generator = generator.apply(__this, __arguments)).next()); | ||
}); | ||
}; | ||
@@ -459,8 +420,7 @@ // ../../node_modules/events/events.js | ||
var OpenFeatureEventEmitter = class extends GenericEventEmitter { | ||
eventEmitter = new import_events.default({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter = new import_events.default({ captureRejections: true }); | ||
this.eventEmitter.on("error", (err) => { | ||
var _a; | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
@@ -477,7 +437,5 @@ } | ||
var NoopFeatureProvider = class { | ||
constructor() { | ||
this.metadata = { | ||
name: "No-op Provider" | ||
}; | ||
} | ||
metadata = { | ||
name: "No-op Provider" | ||
}; | ||
get status() { | ||
@@ -520,2 +478,3 @@ return ProviderStatus.NOT_READY; | ||
var VariantNotFoundError = class extends OpenFeatureError { | ||
code; | ||
constructor(message) { | ||
@@ -531,24 +490,24 @@ super(message); | ||
var InMemoryProvider = class { | ||
events = new OpenFeatureEventEmitter(); | ||
runsOn = "client"; | ||
status = ProviderStatus2.NOT_READY; | ||
metadata = { | ||
name: "in-memory" | ||
}; | ||
_flagConfiguration; | ||
_context; | ||
constructor(flagConfiguration = {}) { | ||
this.events = new OpenFeatureEventEmitter(); | ||
this.runsOn = "client"; | ||
this.status = ProviderStatus2.NOT_READY; | ||
this.metadata = { | ||
name: "in-memory" | ||
}; | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this._flagConfiguration = { ...flagConfiguration }; | ||
} | ||
initialize(context) { | ||
return __async(this, null, function* () { | ||
try { | ||
for (const key in this._flagConfiguration) { | ||
this.resolveFlagWithReason(key, context); | ||
} | ||
this._context = context; | ||
this.status = ProviderStatus2.READY; | ||
} catch (error) { | ||
this.status = ProviderStatus2.ERROR; | ||
throw error; | ||
async initialize(context) { | ||
try { | ||
for (const key in this._flagConfiguration) { | ||
this.resolveFlagWithReason(key, context); | ||
} | ||
}); | ||
this._context = context; | ||
this.status = ProviderStatus2.READY; | ||
} catch (error) { | ||
this.status = ProviderStatus2.ERROR; | ||
throw error; | ||
} | ||
} | ||
@@ -559,17 +518,15 @@ /** | ||
*/ | ||
putConfiguration(flagConfiguration) { | ||
return __async(this, null, function* () { | ||
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key); | ||
this.status = ProviderStatus2.STALE; | ||
this.events.emit(ClientProviderEvents.Stale); | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this.events.emit(ClientProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
try { | ||
yield this.initialize(this._context); | ||
this.events.emit(ClientProviderEvents.Ready); | ||
} catch (err) { | ||
this.events.emit(ClientProviderEvents.Error); | ||
throw err; | ||
} | ||
}); | ||
async putConfiguration(flagConfiguration) { | ||
const flagsChanged = Object.entries(flagConfiguration).filter(([key, value]) => this._flagConfiguration[key] !== value).map(([key]) => key); | ||
this.status = ProviderStatus2.STALE; | ||
this.events.emit(ClientProviderEvents.Stale); | ||
this._flagConfiguration = { ...flagConfiguration }; | ||
this.events.emit(ClientProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
try { | ||
await this.initialize(this._context); | ||
this.events.emit(ClientProviderEvents.Ready); | ||
} catch (err) { | ||
this.events.emit(ClientProviderEvents.Error); | ||
throw err; | ||
} | ||
} | ||
@@ -591,3 +548,3 @@ resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { | ||
const message = `no flag found with key ${flagKey}`; | ||
logger == null ? void 0 : logger.debug(message); | ||
logger?.debug(message); | ||
throw new FlagNotFoundError(message); | ||
@@ -601,3 +558,3 @@ } | ||
const message = `no value associated with variant provided for ${flagKey} found`; | ||
logger == null ? void 0 : logger.error(message); | ||
logger?.error(message); | ||
throw new VariantNotFoundError(message); | ||
@@ -616,3 +573,3 @@ } | ||
if (!(error instanceof OpenFeatureError2)) { | ||
throw new GeneralError((error == null ? void 0 : error.message) || "unknown error"); | ||
throw new GeneralError(error?.message || "unknown error"); | ||
} | ||
@@ -623,14 +580,13 @@ throw error; | ||
lookupFlagValue(flagKey, ctx) { | ||
var _a; | ||
const flagSpec = this._flagConfiguration[flagKey]; | ||
const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator); | ||
const variant = isContextEval ? (_a = flagSpec.contextEvaluator) == null ? void 0 : _a.call(flagSpec, ctx) : flagSpec.defaultVariant; | ||
const value = variant && (flagSpec == null ? void 0 : flagSpec.variants[variant]); | ||
const isContextEval = ctx && flagSpec?.contextEvaluator; | ||
const variant = isContextEval ? flagSpec.contextEvaluator?.(ctx) : flagSpec.defaultVariant; | ||
const value = variant && flagSpec?.variants[variant]; | ||
const evalReason = isContextEval ? StandardResolutionReasons.TARGETING_MATCH : StandardResolutionReasons.STATIC; | ||
const reason = this.status === ProviderStatus2.STALE ? StandardResolutionReasons.CACHED : evalReason; | ||
return __spreadProps(__spreadValues({ | ||
value | ||
}, variant && { variant }), { | ||
return { | ||
value, | ||
...variant && { variant }, | ||
reason | ||
}); | ||
}; | ||
} | ||
@@ -643,8 +599,8 @@ }; | ||
var OpenFeatureAPI = class extends OpenFeatureCommonAPI { | ||
_events = new OpenFeatureEventEmitter(); | ||
_defaultProvider = NOOP_PROVIDER; | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_namedProviderContext = /* @__PURE__ */ new Map(); | ||
constructor() { | ||
super("client"); | ||
this._events = new OpenFeatureEventEmitter(); | ||
this._defaultProvider = NOOP_PROVIDER; | ||
this._createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
this._namedProviderContext = /* @__PURE__ */ new Map(); | ||
} | ||
@@ -665,35 +621,32 @@ /** | ||
} | ||
setContext(nameOrContext, contextOrUndefined) { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
const clientName = stringOrUndefined(nameOrContext); | ||
const context = (_b = (_a = objectOrUndefined(nameOrContext)) != null ? _a : objectOrUndefined(contextOrUndefined)) != null ? _b : {}; | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.set(clientName, context); | ||
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, context); | ||
} else { | ||
this._namedProviderContext.set(clientName, context); | ||
} | ||
async setContext(nameOrContext, contextOrUndefined) { | ||
const clientName = stringOrUndefined(nameOrContext); | ||
const context = objectOrUndefined(nameOrContext) ?? objectOrUndefined(contextOrUndefined) ?? {}; | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.set(clientName, context); | ||
await this.runProviderContextChangeHandler(clientName, provider, oldContext, context); | ||
} else { | ||
const oldContext = this._context; | ||
this._context = context; | ||
const defaultContextNameProviders = Array.from(this._clientProviders.entries()).filter(([name]) => !this._namedProviderContext.has(name)).reduce((acc, [name, provider]) => { | ||
acc.push({ name, provider }); | ||
return acc; | ||
}, []); | ||
const allProviders = [ | ||
// add in the default (no name) | ||
{ name: void 0, provider: this._defaultProvider }, | ||
...defaultContextNameProviders | ||
]; | ||
yield Promise.all( | ||
allProviders.map( | ||
(tuple) => this.runProviderContextChangeHandler(tuple.name, tuple.provider, oldContext, context) | ||
) | ||
); | ||
this._namedProviderContext.set(clientName, context); | ||
} | ||
}); | ||
} else { | ||
const oldContext = this._context; | ||
this._context = context; | ||
const defaultContextNameProviders = Array.from(this._clientProviders.entries()).filter(([name]) => !this._namedProviderContext.has(name)).reduce((acc, [name, provider]) => { | ||
acc.push({ name, provider }); | ||
return acc; | ||
}, []); | ||
const allProviders = [ | ||
// add in the default (no name) | ||
{ name: void 0, provider: this._defaultProvider }, | ||
...defaultContextNameProviders | ||
]; | ||
await Promise.all( | ||
allProviders.map( | ||
(tuple) => this.runProviderContextChangeHandler(tuple.name, tuple.provider, oldContext, context) | ||
) | ||
); | ||
} | ||
} | ||
@@ -712,19 +665,17 @@ getContext(nameOrUndefined) { | ||
} | ||
clearContext(nameOrUndefined) { | ||
return __async(this, null, function* () { | ||
const clientName = stringOrUndefined(nameOrUndefined); | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.delete(clientName); | ||
const newContext = this.getContext(); | ||
yield this.runProviderContextChangeHandler(clientName, provider, oldContext, newContext); | ||
} else { | ||
this._namedProviderContext.delete(clientName); | ||
} | ||
async clearContext(nameOrUndefined) { | ||
const clientName = stringOrUndefined(nameOrUndefined); | ||
if (clientName) { | ||
const provider = this._clientProviders.get(clientName); | ||
if (provider) { | ||
const oldContext = this.getContext(clientName); | ||
this._namedProviderContext.delete(clientName); | ||
const newContext = this.getContext(); | ||
await this.runProviderContextChangeHandler(clientName, provider, oldContext, newContext); | ||
} else { | ||
return this.setContext({}); | ||
this._namedProviderContext.delete(clientName); | ||
} | ||
}); | ||
} else { | ||
return this.setContext({}); | ||
} | ||
} | ||
@@ -735,7 +686,5 @@ /** | ||
*/ | ||
clearContexts() { | ||
return __async(this, null, function* () { | ||
yield this.clearContext(); | ||
yield Promise.allSettled(Array.from(this._clientProviders.keys()).map((name) => this.clearContext(name))); | ||
}); | ||
async clearContexts() { | ||
await this.clearContext(); | ||
await Promise.allSettled(Array.from(this._clientProviders.keys()).map((name) => this.clearContext(name))); | ||
} | ||
@@ -767,28 +716,23 @@ /** | ||
*/ | ||
clearProviders() { | ||
return __async(this, null, function* () { | ||
yield __superGet(OpenFeatureAPI.prototype, this, "clearProvidersAndSetDefault").call(this, NOOP_PROVIDER); | ||
this._namedProviderContext.clear(); | ||
}); | ||
async clearProviders() { | ||
await super.clearProvidersAndSetDefault(NOOP_PROVIDER); | ||
this._namedProviderContext.clear(); | ||
} | ||
runProviderContextChangeHandler(clientName, provider, oldContext, newContext) { | ||
return __async(this, null, function* () { | ||
var _a, _b, _c, _d, _e; | ||
const providerName = provider.metadata.name; | ||
try { | ||
yield (_a = provider.onContextChange) == null ? void 0 : _a.call(provider, oldContext, newContext); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
}); | ||
(_b = this._events) == null ? void 0 : _b.emit(ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
} catch (err) { | ||
const error = err; | ||
const message = `Error running ${(_c = provider == null ? void 0 : provider.metadata) == null ? void 0 : _c.name}'s context change handler: ${error == null ? void 0 : error.message}`; | ||
(_d = this._logger) == null ? void 0 : _d.error(`${message}`, err); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(ClientProviderEvents.Error, { clientName, providerName, message }); | ||
}); | ||
(_e = this._events) == null ? void 0 : _e.emit(ClientProviderEvents.Error, { clientName, providerName, message }); | ||
} | ||
}); | ||
async runProviderContextChangeHandler(clientName, provider, oldContext, newContext) { | ||
const providerName = provider.metadata.name; | ||
try { | ||
await provider.onContextChange?.(oldContext, newContext); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter?.emit(ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
}); | ||
this._events?.emit(ClientProviderEvents.ContextChanged, { clientName, providerName }); | ||
} catch (err) { | ||
const error = err; | ||
const message = `Error running ${provider?.metadata?.name}'s context change handler: ${error?.message}`; | ||
this._logger?.error(`${message}`, err); | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter?.emit(ClientProviderEvents.Error, { clientName, providerName, message }); | ||
}); | ||
this._events?.emit(ClientProviderEvents.Error, { clientName, providerName, message }); | ||
} | ||
} | ||
@@ -805,4 +749,5 @@ }; | ||
this.options = options; | ||
this._hooks = []; | ||
} | ||
_hooks = []; | ||
_clientLogger; | ||
get metadata() { | ||
@@ -816,7 +761,5 @@ return { | ||
get providerStatus() { | ||
var _a; | ||
return ((_a = this.providerAccessor()) == null ? void 0 : _a.status) || ProviderStatus3.READY; | ||
return this.providerAccessor()?.status || ProviderStatus3.READY; | ||
} | ||
addHandler(eventType, handler) { | ||
var _a; | ||
this.emitterAccessor().addHandler(eventType, handler); | ||
@@ -828,3 +771,3 @@ const shouldRunNow = statusMatchesEvent(eventType, this._provider.status); | ||
} catch (err) { | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
this._logger?.error("Error running event handler:", err); | ||
} | ||
@@ -893,3 +836,2 @@ } | ||
evaluate(flagKey, resolver, defaultValue, flagType, options = {}) { | ||
var _a, _b; | ||
const allHooks = [ | ||
@@ -902,3 +844,5 @@ ...OpenFeature.getHooks(), | ||
const allHooksReversed = [...allHooks].reverse(); | ||
const context = __spreadValues({}, OpenFeature.getContext((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.name)); | ||
const context = { | ||
...OpenFeature.getContext(this?.options?.name) | ||
}; | ||
const hookContext = { | ||
@@ -916,11 +860,12 @@ flagKey, | ||
const resolution = resolver.call(this._provider, flagKey, defaultValue, context, this._logger); | ||
const evaluationDetails = __spreadProps(__spreadValues({}, resolution), { | ||
flagMetadata: Object.freeze((_b = resolution.flagMetadata) != null ? _b : {}), | ||
const evaluationDetails = { | ||
...resolution, | ||
flagMetadata: Object.freeze(resolution.flagMetadata ?? {}), | ||
flagKey | ||
}); | ||
}; | ||
this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options); | ||
return evaluationDetails; | ||
} catch (err) { | ||
const errorMessage = err == null ? void 0 : err.message; | ||
const errorCode = (err == null ? void 0 : err.code) || ErrorCode2.GENERAL; | ||
const errorMessage = err?.message; | ||
const errorCode = err?.code || ErrorCode2.GENERAL; | ||
this.errorHooks(allHooksReversed, hookContext, err, options); | ||
@@ -940,20 +885,17 @@ return { | ||
beforeHooks(hooks, hookContext, options) { | ||
var _a; | ||
Object.freeze(hookContext); | ||
Object.freeze(hookContext.context); | ||
for (const hook of hooks) { | ||
(_a = hook == null ? void 0 : hook.before) == null ? void 0 : _a.call(hook, hookContext, Object.freeze(options.hookHints)); | ||
hook?.before?.(hookContext, Object.freeze(options.hookHints)); | ||
} | ||
} | ||
afterHooks(hooks, hookContext, evaluationDetails, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
(_a = hook == null ? void 0 : hook.after) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints); | ||
hook?.after?.(hookContext, evaluationDetails, options.hookHints); | ||
} | ||
} | ||
errorHooks(hooks, hookContext, err, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
try { | ||
(_a = hook == null ? void 0 : hook.error) == null ? void 0 : _a.call(hook, hookContext, err, options.hookHints); | ||
hook?.error?.(hookContext, err, options.hookHints); | ||
} catch (err2) { | ||
@@ -964,3 +906,3 @@ this._logger.error(`Unhandled error during 'error' hook: ${err2}`); | ||
} | ||
this._logger.error(err2 == null ? void 0 : err2.stack); | ||
this._logger.error(err2?.stack); | ||
} | ||
@@ -970,6 +912,5 @@ } | ||
finallyHooks(hooks, hookContext, options) { | ||
var _a; | ||
for (const hook of hooks) { | ||
try { | ||
(_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, options.hookHints); | ||
hook?.finally?.(hookContext, options.hookHints); | ||
} catch (err) { | ||
@@ -980,3 +921,3 @@ this._logger.error(`Unhandled error during 'finally' hook: ${err}`); | ||
} | ||
this._logger.error(err == null ? void 0 : err.stack); | ||
this._logger.error(err?.stack); | ||
} | ||
@@ -983,0 +924,0 @@ } |
@@ -474,3 +474,3 @@ import EventEmitter from 'events'; | ||
abstract code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -480,3 +480,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -486,3 +486,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -492,3 +492,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -498,3 +498,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -504,3 +504,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -510,3 +510,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -516,3 +516,3 @@ | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
constructor(message?: string, options?: ErrorOptions); | ||
} | ||
@@ -519,0 +519,0 @@ |
{ | ||
"name": "@openfeature/web-sdk", | ||
"version": "0.4.10", | ||
"version": "0.4.11", | ||
"description": "OpenFeature SDK for Web", | ||
@@ -20,4 +20,4 @@ "main": "./dist/cjs/index.js", | ||
"clean": "shx rm -rf ./dist", | ||
"build:web-esm": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2016 --platform=browser --format=esm --outfile=./dist/esm/index.js --analyze", | ||
"build:web-cjs": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2016 --platform=browser --format=cjs --outfile=./dist/cjs/index.js --analyze", | ||
"build:web-esm": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2022 --platform=browser --format=esm --outfile=./dist/esm/index.js --analyze", | ||
"build:web-cjs": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2022 --platform=browser --format=cjs --outfile=./dist/cjs/index.js --analyze", | ||
"build:rollup-types": "rollup -c ../../rollup.config.mjs", | ||
@@ -50,7 +50,7 @@ "build": "npm run clean && npm run build:web-esm && npm run build:web-cjs && npm run build:rollup-types", | ||
"peerDependencies": { | ||
"@openfeature/core": "0.0.23" | ||
"@openfeature/core": "0.0.24" | ||
}, | ||
"devDependencies": { | ||
"@openfeature/core": "0.0.23" | ||
"@openfeature/core": "0.0.24" | ||
} | ||
} |
@@ -19,4 +19,4 @@ <!-- markdownlint-disable MD033 --> | ||
<!-- x-release-please-start-version --> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v0.4.10"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.4.10&color=blue&style=for-the-badge" /> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/web-sdk-v0.4.11"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.4.11&color=blue&style=for-the-badge" /> | ||
</a> | ||
@@ -51,3 +51,3 @@ <!-- x-release-please-end --> | ||
- ES2015-compatible web browser (Chrome, Edge, Firefox, etc) | ||
- ES2022-compatible web browser (Chrome, Edge, Firefox, etc) | ||
@@ -54,0 +54,0 @@ ### Install |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
261451
2766