UNPKG

@openfeature/web-sdk

Version:
854 lines (839 loc) 32.8 kB
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() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, 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()); }); }; // ../../node_modules/eventemitter3/index.js var require_eventemitter3 = __commonJS({ "../../node_modules/eventemitter3/index.js"(exports, module) { "use strict"; var has = Object.prototype.hasOwnProperty; var prefix = "~"; function Events() { } if (Object.create) { Events.prototype = /* @__PURE__ */ Object.create(null); if (!new Events().__proto__) prefix = false; } function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } function addListener(emitter, event, fn, context, once) { if (typeof fn !== "function") { throw new TypeError("The listener must be a function"); } var listener = new EE(fn, context || emitter, once), evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } function EventEmitter2() { this._events = new Events(); this._eventsCount = 0; } EventEmitter2.prototype.eventNames = function eventNames() { var names = [], events, name; if (this._eventsCount === 0) return names; for (name in events = this._events) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; EventEmitter2.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event, handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; EventEmitter2.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event, listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; EventEmitter2.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt], len = arguments.length, args, i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, void 0, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len - 1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length, j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, void 0, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len - 1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; EventEmitter2.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; EventEmitter2.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; EventEmitter2.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) { events.push(listeners[i]); } } if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; EventEmitter2.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; EventEmitter2.prototype.off = EventEmitter2.prototype.removeListener; EventEmitter2.prototype.addListener = EventEmitter2.prototype.on; EventEmitter2.prefixed = prefix; EventEmitter2.EventEmitter = EventEmitter2; if ("undefined" !== typeof module) { module.exports = EventEmitter2; } } }); // src/provider/provider.ts import { ClientProviderStatus } from "@openfeature/core"; // src/provider/no-op-provider.ts var REASON_NO_OP = "No-op"; var NoopFeatureProvider = class { constructor() { this.metadata = { name: "No-op Provider" }; } resolveBooleanEvaluation(_, defaultValue) { return this.noOp(defaultValue); } resolveStringEvaluation(_, defaultValue) { return this.noOp(defaultValue); } resolveNumberEvaluation(_, defaultValue) { return this.noOp(defaultValue); } resolveObjectEvaluation(_, defaultValue) { return this.noOp(defaultValue); } noOp(defaultValue) { return { value: defaultValue, reason: REASON_NO_OP }; } }; var NOOP_PROVIDER = new NoopFeatureProvider(); // src/provider/in-memory-provider/in-memory-provider.ts import { FlagNotFoundError, GeneralError, OpenFeatureError as OpenFeatureError2, StandardResolutionReasons, TypeMismatchError } from "@openfeature/core"; // src/events/open-feature-event-emitter.ts import { GenericEventEmitter } from "@openfeature/core"; // ../../node_modules/eventemitter3/index.mjs var import_index = __toESM(require_eventemitter3(), 1); // src/events/open-feature-event-emitter.ts var OpenFeatureEventEmitter = class extends GenericEventEmitter { constructor() { super(); this.eventEmitter = new import_index.default(); } }; // src/events/events.ts import { ClientProviderEvents } from "@openfeature/core"; // src/provider/in-memory-provider/variant-not-found-error.ts import { ErrorCode, OpenFeatureError } from "@openfeature/core"; var VariantNotFoundError = class _VariantNotFoundError extends OpenFeatureError { constructor(message) { super(message); Object.setPrototypeOf(this, _VariantNotFoundError.prototype); this.name = "VariantNotFoundError"; this.code = ErrorCode.GENERAL; } }; // src/provider/in-memory-provider/in-memory-provider.ts var InMemoryProvider = class { constructor(flagConfiguration = {}) { this.events = new OpenFeatureEventEmitter(); this.runsOn = "client"; this.metadata = { name: "in-memory" }; this._flagConfiguration = __spreadValues({}, flagConfiguration); } /** * Overwrites the configured flags. * @param { FlagConfiguration } flagConfiguration new flag configuration */ putConfiguration(flagConfiguration) { return __async(this, null, function* () { try { const flagsChanged = Object.entries(__spreadValues(__spreadValues({}, flagConfiguration), this._flagConfiguration)).map(([key]) => key); this._flagConfiguration = __spreadValues({}, flagConfiguration); this.events.emit(ClientProviderEvents.ConfigurationChanged, { flagsChanged }); } catch (err) { this.events.emit(ClientProviderEvents.Error); throw err; } }); } resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { return this.resolveAndCheckFlag(flagKey, defaultValue, context || this._context, logger); } resolveNumberEvaluation(flagKey, defaultValue, context, logger) { return this.resolveAndCheckFlag(flagKey, defaultValue, context || this._context, logger); } resolveStringEvaluation(flagKey, defaultValue, context, logger) { return this.resolveAndCheckFlag(flagKey, defaultValue, context || this._context, logger); } resolveObjectEvaluation(flagKey, defaultValue, context, logger) { return this.resolveAndCheckFlag(flagKey, defaultValue, context || this._context, logger); } resolveAndCheckFlag(flagKey, defaultValue, context, logger) { if (!(flagKey in this._flagConfiguration)) { const message = `no flag found with key ${flagKey}`; logger == null ? void 0 : logger.debug(message); throw new FlagNotFoundError(message); } if (this._flagConfiguration[flagKey].disabled) { return { value: defaultValue, reason: StandardResolutionReasons.DISABLED }; } const resolvedFlag = this.resolveFlagWithReason(flagKey, context); if (resolvedFlag.value === void 0) { const message = `no value associated with variant provided for ${flagKey} found`; logger == null ? void 0 : logger.error(message); throw new VariantNotFoundError(message); } if (typeof resolvedFlag.value != typeof defaultValue) { throw new TypeMismatchError(); } return resolvedFlag; } resolveFlagWithReason(flagKey, ctx) { try { const resolutionResult = this.lookupFlagValue(flagKey, ctx); return resolutionResult; } catch (error) { if (!(error instanceof OpenFeatureError2)) { throw new GeneralError((error == null ? void 0 : error.message) || "unknown error"); } 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 reason = isContextEval ? StandardResolutionReasons.TARGETING_MATCH : StandardResolutionReasons.STATIC; return __spreadProps(__spreadValues({ value }, variant && { variant }), { reason }); } }; // src/open-feature.ts import { OpenFeatureCommonAPI, ProviderWrapper, objectOrUndefined, stringOrUndefined } from "@openfeature/core"; // src/client/internal/open-feature-client.ts import { ErrorCode as ErrorCode2, ProviderFatalError, ProviderNotReadyError, SafeLogger, StandardResolutionReasons as StandardResolutionReasons2, instantiateErrorByErrorCode, statusMatchesEvent } from "@openfeature/core"; var OpenFeatureClient = class { constructor(providerAccessor, providerStatusAccessor, emitterAccessor, apiContextAccessor, apiHooksAccessor, globalLogger, options) { this.providerAccessor = providerAccessor; this.providerStatusAccessor = providerStatusAccessor; this.emitterAccessor = emitterAccessor; this.apiContextAccessor = apiContextAccessor; this.apiHooksAccessor = apiHooksAccessor; this.globalLogger = globalLogger; this.options = options; this._hooks = []; } get metadata() { var _a, _b; return { // Use domain if name is not provided name: (_a = this.options.domain) != null ? _a : this.options.name, domain: (_b = this.options.domain) != null ? _b : this.options.name, version: this.options.version, providerMetadata: this.providerAccessor().metadata }; } get providerStatus() { return this.providerStatusAccessor(); } addHandler(eventType, handler) { var _a; this.emitterAccessor().addHandler(eventType, handler); const shouldRunNow = statusMatchesEvent(eventType, this.providerStatus); if (shouldRunNow) { try { handler({ clientName: this.metadata.name, domain: this.metadata.domain, providerName: this._provider.metadata.name }); } catch (err) { (_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); } } } removeHandler(notificationType, handler) { this.emitterAccessor().removeHandler(notificationType, handler); } getHandlers(eventType) { return this.emitterAccessor().getHandlers(eventType); } setLogger(logger) { this._clientLogger = new SafeLogger(logger); return this; } addHooks(...hooks) { this._hooks = [...this._hooks, ...hooks]; return this; } getHooks() { return this._hooks; } clearHooks() { this._hooks = []; return this; } getBooleanValue(flagKey, defaultValue, options) { return this.getBooleanDetails(flagKey, defaultValue, options).value; } getBooleanDetails(flagKey, defaultValue, options) { return this.evaluate(flagKey, this._provider.resolveBooleanEvaluation, defaultValue, "boolean", options); } getStringValue(flagKey, defaultValue, options) { return this.getStringDetails(flagKey, defaultValue, options).value; } getStringDetails(flagKey, defaultValue, options) { return this.evaluate( flagKey, // this isolates providers from our restricted string generic argument. this._provider.resolveStringEvaluation, defaultValue, "string", options ); } getNumberValue(flagKey, defaultValue, options) { return this.getNumberDetails(flagKey, defaultValue, options).value; } getNumberDetails(flagKey, defaultValue, options) { return this.evaluate( flagKey, // this isolates providers from our restricted number generic argument. this._provider.resolveNumberEvaluation, defaultValue, "number", options ); } getObjectValue(flagKey, defaultValue, options) { return this.getObjectDetails(flagKey, defaultValue, options).value; } getObjectDetails(flagKey, defaultValue, options) { return this.evaluate(flagKey, this._provider.resolveObjectEvaluation, defaultValue, "object", options); } track(occurrenceKey, occurrenceDetails = {}) { var _a, _b, _c; try { this.shortCircuitIfNotReady(); if (typeof this._provider.track === "function") { const frozenContext = Object.freeze(__spreadValues({}, this.apiContextAccessor((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.domain))); return (_c = (_b = this._provider).track) == null ? void 0 : _c.call(_b, occurrenceKey, frozenContext, occurrenceDetails); } else { this._logger.debug("Provider does not support the track function; will no-op."); } } catch (err) { this._logger.debug("Error recording tracking event.", err); } } evaluate(flagKey, resolver, defaultValue, flagType, options = {}) { var _a, _b; const allHooks = [ ...this.apiHooksAccessor(), ...this.getHooks(), ...options.hooks || [], ...this._provider.hooks || [] ]; const allHooksReversed = [...allHooks].reverse(); const context = __spreadValues({}, this.apiContextAccessor((_a = this == null ? void 0 : this.options) == null ? void 0 : _a.domain)); const hookContext = { flagKey, defaultValue, flagValueType: flagType, clientMetadata: this.metadata, providerMetadata: this._provider.metadata, context, logger: this._logger }; let evaluationDetails; try { this.beforeHooks(allHooks, hookContext, options); this.shortCircuitIfNotReady(); const resolution = resolver.call(this._provider, flagKey, defaultValue, context, this._logger); const resolutionDetails = __spreadProps(__spreadValues({}, resolution), { flagMetadata: Object.freeze((_b = resolution.flagMetadata) != null ? _b : {}), flagKey }); if (resolutionDetails.errorCode) { const err = instantiateErrorByErrorCode(resolutionDetails.errorCode, resolutionDetails.errorMessage); this.errorHooks(allHooksReversed, hookContext, err, options); evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err, resolutionDetails.flagMetadata); } else { this.afterHooks(allHooksReversed, hookContext, resolutionDetails, options); evaluationDetails = resolutionDetails; } } catch (err) { this.errorHooks(allHooksReversed, hookContext, err, options); evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err); } this.finallyHooks(allHooksReversed, hookContext, evaluationDetails, options); return evaluationDetails; } 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)); } } 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); } } 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); } catch (err2) { this._logger.error(`Unhandled error during 'error' hook: ${err2}`); if (err2 instanceof Error) { this._logger.error(err2.stack); } this._logger.error(err2 == null ? void 0 : err2.stack); } } } finallyHooks(hooks, hookContext, evaluationDetails, options) { var _a; for (const hook of hooks) { try { (_a = hook == null ? void 0 : hook.finally) == null ? void 0 : _a.call(hook, hookContext, evaluationDetails, options.hookHints); } catch (err) { this._logger.error(`Unhandled error during 'finally' hook: ${err}`); if (err instanceof Error) { this._logger.error(err.stack); } this._logger.error(err == null ? void 0 : err.stack); } } } get _provider() { return this.providerAccessor(); } get _logger() { return this._clientLogger || this.globalLogger(); } shortCircuitIfNotReady() { if (this.providerStatus === ClientProviderStatus.NOT_READY) { throw new ProviderNotReadyError("provider has not yet initialized"); } else if (this.providerStatus === ClientProviderStatus.FATAL) { throw new ProviderFatalError("provider is in an irrecoverable error state"); } } getErrorEvaluationDetails(flagKey, defaultValue, err, flagMetadata = {}) { const errorMessage = err == null ? void 0 : err.message; const errorCode = (err == null ? void 0 : err.code) || ErrorCode2.GENERAL; return { errorCode, errorMessage, value: defaultValue, reason: StandardResolutionReasons2.ERROR, flagMetadata: Object.freeze(flagMetadata), flagKey }; } }; // src/open-feature.ts var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api"); var _globalThis = globalThis; var OpenFeatureAPI = class _OpenFeatureAPI extends OpenFeatureCommonAPI { constructor() { super("client"); this._statusEnumType = ClientProviderStatus; this._apiEmitter = new OpenFeatureEventEmitter(); this._defaultProvider = new ProviderWrapper( NOOP_PROVIDER, ClientProviderStatus.NOT_READY, this._statusEnumType ); this._domainScopedProviders = /* @__PURE__ */ new Map(); this._createEventEmitter = () => new OpenFeatureEventEmitter(); } /** * Gets a singleton instance of the OpenFeature API. * @ignore * @returns {OpenFeatureAPI} OpenFeature API */ static getInstance() { const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY]; if (globalApi) { return globalApi; } const instance = new _OpenFeatureAPI(); _globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance; return instance; } getProviderStatus(domain) { var _a, _b; if (!domain) { return this._defaultProvider.status; } return (_b = (_a = this._domainScopedProviders.get(domain)) == null ? void 0 : _a.status) != null ? _b : this._defaultProvider.status; } setProviderAndWait(clientOrProvider, providerContextOrUndefined, contextOrUndefined) { return __async(this, null, function* () { const domain = stringOrUndefined(clientOrProvider); const provider = domain ? objectOrUndefined(providerContextOrUndefined) : objectOrUndefined(clientOrProvider); const context = domain ? objectOrUndefined(contextOrUndefined) : objectOrUndefined(providerContextOrUndefined); if (context) { if (domain) { this._domainScopedContext.set(domain, context); } else { this._context = context; } } yield this.setAwaitableProvider(domain, provider); }); } setProvider(domainOrProvider, providerContextOrUndefined, contextOrUndefined) { const domain = stringOrUndefined(domainOrProvider); const provider = domain ? objectOrUndefined(providerContextOrUndefined) : objectOrUndefined(domainOrProvider); const context = domain ? objectOrUndefined(contextOrUndefined) : objectOrUndefined(providerContextOrUndefined); if (context) { if (domain) { this._domainScopedContext.set(domain, context); } else { this._context = context; } } const maybePromise = this.setAwaitableProvider(domain, provider); Promise.resolve(maybePromise).catch((err) => { this._logger.error("Error during provider initialization:", err); }); return this; } setContext(domainOrContext, contextOrUndefined) { return __async(this, null, function* () { var _a, _b; const domain = stringOrUndefined(domainOrContext); const context = (_b = (_a = objectOrUndefined(domainOrContext)) != null ? _a : objectOrUndefined(contextOrUndefined)) != null ? _b : {}; if (domain) { const wrapper = this._domainScopedProviders.get(domain); if (wrapper) { const oldContext = this.getContext(domain); this._domainScopedContext.set(domain, context); yield this.runProviderContextChangeHandler(domain, wrapper, oldContext, context); } else { this._domainScopedContext.set(domain, context); } } else { const oldContext = this._context; this._context = context; const unboundProviders = Array.from(this._domainScopedProviders.entries()).filter(([domain2]) => !this._domainScopedContext.has(domain2)).reduce((acc, [domain2, wrapper]) => { acc.push({ domain: domain2, wrapper }); return acc; }, []); const allDomainRecords = [ // add in the default (no domain) { domain: void 0, wrapper: this._defaultProvider }, ...unboundProviders ]; yield Promise.all( allDomainRecords.map((dm) => this.runProviderContextChangeHandler(dm.domain, dm.wrapper, oldContext, context)) ); } }); } getContext(domainOrUndefined) { const domain = stringOrUndefined(domainOrUndefined); if (domain) { const context = this._domainScopedContext.get(domain); if (context) { return context; } else { this._logger.debug(`Unable to find context for '${domain}'.`); } } return this._context; } clearContext(domainOrUndefined) { return __async(this, null, function* () { const domain = stringOrUndefined(domainOrUndefined); if (domain) { const wrapper = this._domainScopedProviders.get(domain); if (wrapper) { const oldContext = this.getContext(domain); this._domainScopedContext.delete(domain); const newContext = this.getContext(); yield this.runProviderContextChangeHandler(domain, wrapper, oldContext, newContext); } else { this._domainScopedContext.delete(domain); } } else { return this.setContext({}); } }); } /** * Resets the global evaluation context and removes the evaluation context for * all domains. */ clearContexts() { return __async(this, null, function* () { yield this.clearContext(); yield Promise.allSettled(Array.from(this._domainScopedProviders.keys()).map((domain) => this.clearContext(domain))); }); } /** * A factory function for creating new named OpenFeature clients. Clients can contain * their own state (e.g. logger, hook, context). Multiple clients can be used * to segment feature flag configuration. * * If there is already a provider bound to this name via {@link this.setProvider setProvider}, this provider will be used. * Otherwise, the default provider is used until a provider is assigned to that name. * @param {string} domain An identifier which logically binds clients with providers * @param {string} version The version of the client (only used for metadata) * @returns {Client} OpenFeature Client */ getClient(domain, version) { return new OpenFeatureClient( // functions are passed here to make sure that these values are always up to date, // and so we don't have to make these public properties on the API class. () => this.getProviderForClient(domain), () => this.getProviderStatus(domain), () => this.buildAndCacheEventEmitterForClient(domain), (domain2) => this.getContext(domain2), () => this.getHooks(), () => this._logger, { domain, version } ); } /** * Clears all registered providers and resets the default provider. * @returns {Promise<void>} */ clearProviders() { return __async(this, null, function* () { yield __superGet(_OpenFeatureAPI.prototype, this, "clearProvidersAndSetDefault").call(this, NOOP_PROVIDER); this._domainScopedContext.clear(); }); } runProviderContextChangeHandler(domain, wrapper, oldContext, newContext) { return __async(this, null, function* () { var _a, _b, _c, _d, _e, _f; const providerName = ((_b = (_a = wrapper.provider) == null ? void 0 : _a.metadata) == null ? void 0 : _b.name) || "unnamed-provider"; try { if (typeof wrapper.provider.onContextChange === "function") { const maybePromise = wrapper.provider.onContextChange(oldContext, newContext); if (typeof (maybePromise == null ? void 0 : maybePromise.then) === "function") { wrapper.incrementPendingContextChanges(); wrapper.status = this._statusEnumType.RECONCILING; this.getAssociatedEventEmitters(domain).forEach((emitter) => { emitter == null ? void 0 : emitter.emit(ClientProviderEvents.Reconciling, { domain, providerName }); }); (_c = this._apiEmitter) == null ? void 0 : _c.emit(ClientProviderEvents.Reconciling, { domain, providerName }); yield maybePromise; wrapper.decrementPendingContextChanges(); } } wrapper.status = this._statusEnumType.READY; if (wrapper.allContextChangesSettled) { this.getAssociatedEventEmitters(domain).forEach((emitter) => { emitter == null ? void 0 : emitter.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName }); }); (_d = this._apiEmitter) == null ? void 0 : _d.emit(ClientProviderEvents.ContextChanged, { clientName: domain, domain, providerName }); } } catch (err) { wrapper.decrementPendingContextChanges(); wrapper.status = this._statusEnumType.ERROR; if (wrapper.allContextChangesSettled) { const error = err; const message = `Error running ${providerName}'s context change handler: ${error == null ? void 0 : error.message}`; (_e = this._logger) == null ? void 0 : _e.error(`${message}`, err); this.getAssociatedEventEmitters(domain).forEach((emitter) => { emitter == null ? void 0 : emitter.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message }); }); (_f = this._apiEmitter) == null ? void 0 : _f.emit(ClientProviderEvents.Error, { clientName: domain, domain, providerName, message }); } } }); } }; var OpenFeature = OpenFeatureAPI.getInstance(); // src/index.ts export * from "@openfeature/core"; export { InMemoryProvider, NOOP_PROVIDER, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter, ClientProviderEvents as ProviderEvents, ClientProviderStatus as ProviderStatus }; //# sourceMappingURL=index.js.map