@openfeature/web-sdk
Advanced tools
Comparing version 0.3.2-experimental to 0.3.3-experimental
@@ -97,11 +97,11 @@ "use strict"; | ||
}; | ||
function EventEmitter() { | ||
EventEmitter.init.call(this); | ||
function EventEmitter2() { | ||
EventEmitter2.init.call(this); | ||
} | ||
module2.exports = EventEmitter; | ||
module2.exports = EventEmitter2; | ||
module2.exports.once = once; | ||
EventEmitter.EventEmitter = EventEmitter; | ||
EventEmitter.prototype._events = void 0; | ||
EventEmitter.prototype._eventsCount = 0; | ||
EventEmitter.prototype._maxListeners = void 0; | ||
EventEmitter2.EventEmitter = EventEmitter2; | ||
EventEmitter2.prototype._events = void 0; | ||
EventEmitter2.prototype._eventsCount = 0; | ||
EventEmitter2.prototype._maxListeners = void 0; | ||
var defaultMaxListeners = 10; | ||
@@ -113,3 +113,3 @@ function checkListener(listener) { | ||
} | ||
Object.defineProperty(EventEmitter, "defaultMaxListeners", { | ||
Object.defineProperty(EventEmitter2, "defaultMaxListeners", { | ||
enumerable: true, | ||
@@ -126,3 +126,3 @@ get: function() { | ||
}); | ||
EventEmitter.init = function() { | ||
EventEmitter2.init = function() { | ||
if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) { | ||
@@ -134,3 +134,3 @@ this._events = /* @__PURE__ */ Object.create(null); | ||
}; | ||
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { | ||
EventEmitter2.prototype.setMaxListeners = function setMaxListeners(n) { | ||
if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) { | ||
@@ -144,9 +144,9 @@ throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + "."); | ||
if (that._maxListeners === void 0) | ||
return EventEmitter.defaultMaxListeners; | ||
return EventEmitter2.defaultMaxListeners; | ||
return that._maxListeners; | ||
} | ||
EventEmitter.prototype.getMaxListeners = function getMaxListeners() { | ||
EventEmitter2.prototype.getMaxListeners = function getMaxListeners() { | ||
return _getMaxListeners(this); | ||
}; | ||
EventEmitter.prototype.emit = function emit(type) { | ||
EventEmitter2.prototype.emit = function emit(type) { | ||
var args = []; | ||
@@ -229,7 +229,7 @@ for (var i = 1; i < arguments.length; i++) | ||
} | ||
EventEmitter.prototype.addListener = function addListener(type, listener) { | ||
EventEmitter2.prototype.addListener = function addListener(type, listener) { | ||
return _addListener(this, type, listener, false); | ||
}; | ||
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | ||
EventEmitter.prototype.prependListener = function prependListener(type, listener) { | ||
EventEmitter2.prototype.on = EventEmitter2.prototype.addListener; | ||
EventEmitter2.prototype.prependListener = function prependListener(type, listener) { | ||
return _addListener(this, type, listener, true); | ||
@@ -253,3 +253,3 @@ }; | ||
} | ||
EventEmitter.prototype.once = function once2(type, listener) { | ||
EventEmitter2.prototype.once = function once2(type, listener) { | ||
checkListener(listener); | ||
@@ -259,3 +259,3 @@ this.on(type, _onceWrap(this, type, listener)); | ||
}; | ||
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { | ||
EventEmitter2.prototype.prependOnceListener = function prependOnceListener(type, listener) { | ||
checkListener(listener); | ||
@@ -265,3 +265,3 @@ this.prependListener(type, _onceWrap(this, type, listener)); | ||
}; | ||
EventEmitter.prototype.removeListener = function removeListener(type, listener) { | ||
EventEmitter2.prototype.removeListener = function removeListener(type, listener) { | ||
var list, events, position, i, originalListener; | ||
@@ -306,4 +306,4 @@ checkListener(listener); | ||
}; | ||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener; | ||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { | ||
EventEmitter2.prototype.off = EventEmitter2.prototype.removeListener; | ||
EventEmitter2.prototype.removeAllListeners = function removeAllListeners(type) { | ||
var listeners, events, i; | ||
@@ -360,9 +360,9 @@ events = this._events; | ||
} | ||
EventEmitter.prototype.listeners = function listeners(type) { | ||
EventEmitter2.prototype.listeners = function listeners(type) { | ||
return _listeners(this, type, true); | ||
}; | ||
EventEmitter.prototype.rawListeners = function rawListeners(type) { | ||
EventEmitter2.prototype.rawListeners = function rawListeners(type) { | ||
return _listeners(this, type, false); | ||
}; | ||
EventEmitter.listenerCount = function(emitter, type) { | ||
EventEmitter2.listenerCount = function(emitter, type) { | ||
if (typeof emitter.listenerCount === "function") { | ||
@@ -374,3 +374,3 @@ return emitter.listenerCount(type); | ||
}; | ||
EventEmitter.prototype.listenerCount = listenerCount; | ||
EventEmitter2.prototype.listenerCount = listenerCount; | ||
function listenerCount(type) { | ||
@@ -388,3 +388,3 @@ var events = this._events; | ||
} | ||
EventEmitter.prototype.eventNames = function eventNames() { | ||
EventEmitter2.prototype.eventNames = function eventNames() { | ||
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; | ||
@@ -458,3 +458,2 @@ }; | ||
__export(src_exports, { | ||
ApiEvents: () => ApiEvents, | ||
DefaultLogger: () => DefaultLogger, | ||
@@ -472,5 +471,6 @@ ErrorCode: () => ErrorCode, | ||
OpenFeatureError: () => OpenFeatureError, | ||
OpenFeatureEventEmitter: () => import_events.EventEmitter, | ||
OpenFeatureEventEmitter: () => OpenFeatureEventEmitter, | ||
ParseError: () => ParseError, | ||
ProviderEvents: () => ProviderEvents, | ||
ProviderStatus: () => ProviderStatus, | ||
SafeLogger: () => SafeLogger, | ||
@@ -498,3 +498,3 @@ StandardResolutionReasons: () => StandardResolutionReasons, | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
@@ -531,2 +531,8 @@ DEFAULT: "DEFAULT", | ||
})(ErrorCode || {}); | ||
var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => { | ||
ProviderStatus2["NOT_READY"] = "NOT_READY"; | ||
ProviderStatus2["READY"] = "READY"; | ||
ProviderStatus2["ERROR"] = "ERROR"; | ||
return ProviderStatus2; | ||
})(ProviderStatus || {}); | ||
@@ -664,2 +670,72 @@ // ../shared/src/errors/open-feature-error-abstract.ts | ||
// ../shared/src/events.ts | ||
var import_events = __toESM(require_events()); | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var OpenFeatureEventEmitter = class { | ||
constructor(globalLogger) { | ||
this.globalLogger = globalLogger; | ||
this._handlers = /* @__PURE__ */ new WeakMap(); | ||
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); | ||
}); | ||
} | ||
emit(eventType, context) { | ||
this.eventEmitter.emit(eventType, context); | ||
} | ||
addHandler(eventType, handler) { | ||
const asyncHandler = (context) => __async(this, null, function* () { | ||
yield handler(context); | ||
}); | ||
this._handlers.set(handler, asyncHandler); | ||
this.eventEmitter.on(eventType, asyncHandler); | ||
} | ||
removeHandler(eventType, handler) { | ||
const asyncHandler = this._handlers.get(handler); | ||
if (!asyncHandler) { | ||
return; | ||
} | ||
this.eventEmitter.removeListener(eventType, asyncHandler); | ||
} | ||
removeAllHandlers(eventType) { | ||
if (eventType) { | ||
this.eventEmitter.removeAllListeners(eventType); | ||
} else { | ||
this.eventEmitter.removeAllListeners(); | ||
} | ||
} | ||
getHandlers(eventType) { | ||
return this.eventEmitter.listeners(eventType); | ||
} | ||
setLogger(logger) { | ||
this._eventLogger = new SafeLogger(logger); | ||
return this; | ||
} | ||
get _logger() { | ||
var _a; | ||
return this._eventLogger || ((_a = this.globalLogger) == null ? void 0 : _a.call(this)); | ||
} | ||
}; | ||
// ../shared/src/type-guards.ts | ||
function isString(value) { | ||
return typeof value === "string"; | ||
} | ||
function stringOrUndefined(value) { | ||
return isString(value) ? value : void 0; | ||
} | ||
function isObject(value) { | ||
return typeof value === "object"; | ||
} | ||
function objectOrUndefined(value) { | ||
return isObject(value) ? value : void 0; | ||
} | ||
// ../shared/src/open-feature.ts | ||
@@ -671,6 +747,137 @@ var OpenFeatureCommonAPI = class { | ||
this._logger = new DefaultLogger(); | ||
this._events = new OpenFeatureEventEmitter(() => this._logger); | ||
this._clientProviders = /* @__PURE__ */ new Map(); | ||
this._clientEvents = /* @__PURE__ */ new Map(); | ||
} | ||
setLogger(logger) { | ||
this._logger = new SafeLogger(logger); | ||
return this; | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._defaultProvider.metadata; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* When changing the provider, the currently attached handlers will listen to the events of the new provider. | ||
* @param {ProviderEvents} eventType The provider event type to listen to | ||
* @param {EventHandler} handler The handler to run on occurrence of the event type | ||
*/ | ||
addHandler(eventType, handler) { | ||
this._events.addHandler(eventType, handler); | ||
} | ||
/** | ||
* Removes a handler for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to remove the listener for | ||
* @param {EventHandler} handler The handler to remove for the provider event type | ||
*/ | ||
removeHandler(eventType, handler) { | ||
this._events.removeHandler(eventType, handler); | ||
} | ||
/** | ||
* Gets the current handlers for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to get the current handlers for | ||
* @returns {EventHandler[]} The handlers currently attached to the given provider event type | ||
*/ | ||
getHandlers(eventType) { | ||
return this._events.getHandlers(eventType); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
var _a, _b, _c, _d, _e, _f; | ||
const clientName = stringOrUndefined(clientOrProvider); | ||
const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined); | ||
if (!provider) { | ||
return this; | ||
} | ||
const oldProvider = this.getProviderForClient(clientName); | ||
if (oldProvider === provider) { | ||
return this; | ||
} | ||
const clientEmitter = this.getEventEmitterForClient(clientName); | ||
if (typeof provider.initialize === "function") { | ||
(_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => { | ||
var _a2; | ||
clientEmitter.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
})) == null ? void 0 : _d.catch((error) => { | ||
var _a2; | ||
clientEmitter.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message }); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message }); | ||
}); | ||
} else { | ||
clientEmitter.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
(_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
} | ||
if (clientName) { | ||
this._clientProviders.set(clientName, provider); | ||
} else { | ||
this._defaultProvider = provider; | ||
} | ||
this.transferListeners(oldProvider, provider, clientName, clientEmitter); | ||
if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) { | ||
(_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider); | ||
} | ||
return this; | ||
} | ||
getProviderForClient(name) { | ||
var _a; | ||
if (!name) { | ||
return this._defaultProvider; | ||
} | ||
return (_a = this._clientProviders.get(name)) != null ? _a : this._defaultProvider; | ||
} | ||
getEventEmitterForClient(name) { | ||
const emitter = this._clientEvents.get(name); | ||
if (emitter) { | ||
return emitter; | ||
} | ||
const newEmitter = new OpenFeatureEventEmitter(() => this._logger); | ||
this._clientEvents.set(name, newEmitter); | ||
return newEmitter; | ||
} | ||
transferListeners(oldProvider, newProvider, clientName, clientEmitter) { | ||
var _a; | ||
(_a = oldProvider.events) == null ? void 0 : _a.removeAllHandlers(); | ||
Object.values(ProviderEvents).forEach( | ||
(eventType) => { | ||
var _a2; | ||
return (_a2 = newProvider.events) == null ? void 0 : _a2.addHandler(eventType, (details) => __async(this, null, function* () { | ||
clientEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName })); | ||
this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName })); | ||
})); | ||
} | ||
); | ||
} | ||
close() { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
try { | ||
yield (_b = (_a = this == null ? void 0 : this._defaultProvider) == null ? void 0 : _a.onClose) == null ? void 0 : _b.call(_a); | ||
} catch (err) { | ||
this.handleShutdownError(this._defaultProvider, err); | ||
} | ||
const providers = Array.from(this._clientProviders); | ||
yield Promise.all( | ||
providers.map((_0) => __async(this, [_0], function* ([, provider]) { | ||
var _a2; | ||
try { | ||
yield (_a2 = provider.onClose) == null ? void 0 : _a2.call(provider); | ||
} catch (err) { | ||
this.handleShutdownError(this._defaultProvider, err); | ||
} | ||
})) | ||
); | ||
}); | ||
} | ||
handleShutdownError(provider, err) { | ||
this._logger.error(`Error during shutdown of provider ${provider.metadata.name}: ${err}`); | ||
this._logger.error(err == null ? void 0 : err.stack); | ||
} | ||
setTransactionContextPropagator(transactionContextPropagator) { | ||
@@ -710,2 +917,5 @@ const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
} | ||
get status() { | ||
return "NOT_READY" /* NOT_READY */; | ||
} | ||
resolveBooleanEvaluation(_, defaultValue) { | ||
@@ -732,18 +942,4 @@ return this.noOp(defaultValue); | ||
// src/types.ts | ||
var import_events = __toESM(require_events()); | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var ApiEvents = /* @__PURE__ */ ((ApiEvents2) => { | ||
ApiEvents2["ProviderChanged"] = "providerChanged"; | ||
return ApiEvents2; | ||
})(ApiEvents || {}); | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js.api"); | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api"); | ||
var _globalThis = globalThis; | ||
@@ -754,10 +950,7 @@ var OpenFeatureAPI = class extends OpenFeatureCommonAPI { | ||
super(); | ||
this._apiEvents = new import_events.EventEmitter(); | ||
this._providerReady = false; | ||
this._hooks = []; | ||
this._provider = NOOP_PROVIDER; | ||
this._defaultProvider = NOOP_PROVIDER; | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* | ||
* @ignore | ||
@@ -775,10 +968,2 @@ * @returns {OpenFeatureAPI} OpenFeature API | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._provider.metadata; | ||
} | ||
setLogger(logger) { | ||
@@ -804,38 +989,16 @@ this._logger = new SafeLogger(logger); | ||
this._context = context; | ||
yield (_b = (_a = this._provider) == null ? void 0 : _a.onContextChange) == null ? void 0 : _b.call(_a, oldContext, context); | ||
yield (_b = (_a = this._defaultProvider) == null ? void 0 : _a.onContextChange) == null ? void 0 : _b.call(_a, oldContext, context); | ||
}); | ||
} | ||
setProvider(provider) { | ||
var _a, _b, _c, _d, _e, _f, _g; | ||
if (this._provider !== provider) { | ||
const oldProvider = this._provider; | ||
this._provider = provider; | ||
this._providerReady = false; | ||
if (!this._provider.events) { | ||
this._provider.events = new import_events.EventEmitter(); | ||
} | ||
if (typeof ((_a = this._provider) == null ? void 0 : _a.initialize) === "function") { | ||
(_e = (_d = (_c = (_b = this._provider).initialize) == null ? void 0 : _c.call(_b, this._context)) == null ? void 0 : _d.then(() => { | ||
var _a2; | ||
this._providerReady = true; | ||
(_a2 = this._provider.events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */); | ||
})) == null ? void 0 : _e.catch(() => { | ||
var _a2; | ||
(_a2 = this._provider.events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */); | ||
}); | ||
} else { | ||
this._providerReady = true; | ||
(_f = this._provider.events) == null ? void 0 : _f.emit("PROVIDER_READY" /* Ready */); | ||
} | ||
this._apiEvents.emit("providerChanged" /* ProviderChanged */); | ||
(_g = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _g.call(oldProvider); | ||
} | ||
return this; | ||
} | ||
close() { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
yield (_b = (_a = this == null ? void 0 : this._provider) == null ? void 0 : _a.onClose) == null ? void 0 : _b.call(_a); | ||
}); | ||
} | ||
/** | ||
* 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} name The name of the client | ||
* @param {string} version The version of the client (only used for metadata) | ||
* @returns {Client} OpenFeature Client | ||
*/ | ||
getClient(name, version) { | ||
@@ -845,5 +1008,4 @@ return new OpenFeatureClient( | ||
// and so we don't have to make these public properties on the API class. | ||
() => this._provider, | ||
() => this._providerReady, | ||
() => this._apiEvents, | ||
() => this.getProviderForClient(name), | ||
() => this.getEventEmitterForClient(name), | ||
() => this._logger, | ||
@@ -858,23 +1020,29 @@ { name, version } | ||
var OpenFeatureClient = class { | ||
constructor(providerAccessor, providerReady, apiEvents, globalLogger, options) { | ||
constructor(providerAccessor, events, globalLogger, options) { | ||
this.providerAccessor = providerAccessor; | ||
this.providerReady = providerReady; | ||
this.events = events; | ||
this.globalLogger = globalLogger; | ||
this.options = options; | ||
this._hooks = []; | ||
this._handlerWrappers = []; | ||
this.metadata = { | ||
name: options.name, | ||
version: options.version | ||
} | ||
get metadata() { | ||
return { | ||
name: this.options.name, | ||
version: this.options.version, | ||
providerMetadata: this.providerAccessor().metadata | ||
}; | ||
this.attachListeners(); | ||
apiEvents().on("providerChanged" /* ProviderChanged */, () => { | ||
this.attachListeners(); | ||
}); | ||
} | ||
addHandler(eventType, handler) { | ||
this._handlerWrappers.push({ eventType, handler }); | ||
if (eventType === "PROVIDER_READY" /* Ready */ && this.providerReady()) { | ||
handler(); | ||
this.events().addHandler(eventType, handler); | ||
const providerReady = !this._provider.status || this._provider.status === "READY" /* READY */; | ||
if (eventType === "PROVIDER_READY" /* Ready */ && providerReady) { | ||
handler({ clientName: this.metadata.name }); | ||
} | ||
} | ||
removeHandler(notificationType, handler) { | ||
this.events().removeHandler(notificationType, handler); | ||
} | ||
getHandlers(eventType) { | ||
return this.events().getHandlers(eventType); | ||
} | ||
setLogger(logger) { | ||
@@ -899,9 +1067,3 @@ this._clientLogger = new SafeLogger(logger); | ||
getBooleanDetails(flagKey, defaultValue, options) { | ||
return this.evaluate( | ||
flagKey, | ||
this._provider.resolveBooleanEvaluation, | ||
defaultValue, | ||
"boolean", | ||
options | ||
); | ||
return this.evaluate(flagKey, this._provider.resolveBooleanEvaluation, defaultValue, "boolean", options); | ||
} | ||
@@ -941,2 +1103,3 @@ getStringValue(flagKey, defaultValue, options) { | ||
evaluate(flagKey, resolver, defaultValue, flagType, options = {}) { | ||
var _a; | ||
const allHooks = [ | ||
@@ -963,2 +1126,3 @@ ...OpenFeature.getHooks(), | ||
const evaluationDetails = __spreadProps(__spreadValues({}, resolution), { | ||
flagMetadata: Object.freeze((_a = resolution.flagMetadata) != null ? _a : {}), | ||
flagKey | ||
@@ -977,2 +1141,3 @@ }); | ||
reason: StandardResolutionReasons.ERROR, | ||
flagMetadata: Object.freeze({}), | ||
flagKey | ||
@@ -1032,11 +1197,3 @@ }; | ||
} | ||
attachListeners() { | ||
Object.values(ProviderEvents).forEach((eventType) => { | ||
var _a; | ||
return (_a = this._provider.events) == null ? void 0 : _a.on(eventType, () => { | ||
this._handlerWrappers.filter((wrapper) => wrapper.eventType === eventType).forEach((wrapper) => wrapper.handler()); | ||
}); | ||
}); | ||
} | ||
}; | ||
//# sourceMappingURL=index.js.map |
@@ -91,11 +91,11 @@ var __create = Object.create; | ||
}; | ||
function EventEmitter() { | ||
EventEmitter.init.call(this); | ||
function EventEmitter2() { | ||
EventEmitter2.init.call(this); | ||
} | ||
module.exports = EventEmitter; | ||
module.exports = EventEmitter2; | ||
module.exports.once = once; | ||
EventEmitter.EventEmitter = EventEmitter; | ||
EventEmitter.prototype._events = void 0; | ||
EventEmitter.prototype._eventsCount = 0; | ||
EventEmitter.prototype._maxListeners = void 0; | ||
EventEmitter2.EventEmitter = EventEmitter2; | ||
EventEmitter2.prototype._events = void 0; | ||
EventEmitter2.prototype._eventsCount = 0; | ||
EventEmitter2.prototype._maxListeners = void 0; | ||
var defaultMaxListeners = 10; | ||
@@ -107,3 +107,3 @@ function checkListener(listener) { | ||
} | ||
Object.defineProperty(EventEmitter, "defaultMaxListeners", { | ||
Object.defineProperty(EventEmitter2, "defaultMaxListeners", { | ||
enumerable: true, | ||
@@ -120,3 +120,3 @@ get: function() { | ||
}); | ||
EventEmitter.init = function() { | ||
EventEmitter2.init = function() { | ||
if (this._events === void 0 || this._events === Object.getPrototypeOf(this)._events) { | ||
@@ -128,3 +128,3 @@ this._events = /* @__PURE__ */ Object.create(null); | ||
}; | ||
EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) { | ||
EventEmitter2.prototype.setMaxListeners = function setMaxListeners(n) { | ||
if (typeof n !== "number" || n < 0 || NumberIsNaN(n)) { | ||
@@ -138,9 +138,9 @@ throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + "."); | ||
if (that._maxListeners === void 0) | ||
return EventEmitter.defaultMaxListeners; | ||
return EventEmitter2.defaultMaxListeners; | ||
return that._maxListeners; | ||
} | ||
EventEmitter.prototype.getMaxListeners = function getMaxListeners() { | ||
EventEmitter2.prototype.getMaxListeners = function getMaxListeners() { | ||
return _getMaxListeners(this); | ||
}; | ||
EventEmitter.prototype.emit = function emit(type) { | ||
EventEmitter2.prototype.emit = function emit(type) { | ||
var args = []; | ||
@@ -223,7 +223,7 @@ for (var i = 1; i < arguments.length; i++) | ||
} | ||
EventEmitter.prototype.addListener = function addListener(type, listener) { | ||
EventEmitter2.prototype.addListener = function addListener(type, listener) { | ||
return _addListener(this, type, listener, false); | ||
}; | ||
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | ||
EventEmitter.prototype.prependListener = function prependListener(type, listener) { | ||
EventEmitter2.prototype.on = EventEmitter2.prototype.addListener; | ||
EventEmitter2.prototype.prependListener = function prependListener(type, listener) { | ||
return _addListener(this, type, listener, true); | ||
@@ -247,3 +247,3 @@ }; | ||
} | ||
EventEmitter.prototype.once = function once2(type, listener) { | ||
EventEmitter2.prototype.once = function once2(type, listener) { | ||
checkListener(listener); | ||
@@ -253,3 +253,3 @@ this.on(type, _onceWrap(this, type, listener)); | ||
}; | ||
EventEmitter.prototype.prependOnceListener = function prependOnceListener(type, listener) { | ||
EventEmitter2.prototype.prependOnceListener = function prependOnceListener(type, listener) { | ||
checkListener(listener); | ||
@@ -259,3 +259,3 @@ this.prependListener(type, _onceWrap(this, type, listener)); | ||
}; | ||
EventEmitter.prototype.removeListener = function removeListener(type, listener) { | ||
EventEmitter2.prototype.removeListener = function removeListener(type, listener) { | ||
var list, events, position, i, originalListener; | ||
@@ -300,4 +300,4 @@ checkListener(listener); | ||
}; | ||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener; | ||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(type) { | ||
EventEmitter2.prototype.off = EventEmitter2.prototype.removeListener; | ||
EventEmitter2.prototype.removeAllListeners = function removeAllListeners(type) { | ||
var listeners, events, i; | ||
@@ -354,9 +354,9 @@ events = this._events; | ||
} | ||
EventEmitter.prototype.listeners = function listeners(type) { | ||
EventEmitter2.prototype.listeners = function listeners(type) { | ||
return _listeners(this, type, true); | ||
}; | ||
EventEmitter.prototype.rawListeners = function rawListeners(type) { | ||
EventEmitter2.prototype.rawListeners = function rawListeners(type) { | ||
return _listeners(this, type, false); | ||
}; | ||
EventEmitter.listenerCount = function(emitter, type) { | ||
EventEmitter2.listenerCount = function(emitter, type) { | ||
if (typeof emitter.listenerCount === "function") { | ||
@@ -368,3 +368,3 @@ return emitter.listenerCount(type); | ||
}; | ||
EventEmitter.prototype.listenerCount = listenerCount; | ||
EventEmitter2.prototype.listenerCount = listenerCount; | ||
function listenerCount(type) { | ||
@@ -382,3 +382,3 @@ var events = this._events; | ||
} | ||
EventEmitter.prototype.eventNames = function eventNames() { | ||
EventEmitter2.prototype.eventNames = function eventNames() { | ||
return this._eventsCount > 0 ? ReflectOwnKeys(this._events) : []; | ||
@@ -464,3 +464,3 @@ }; | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
@@ -497,2 +497,8 @@ DEFAULT: "DEFAULT", | ||
})(ErrorCode || {}); | ||
var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => { | ||
ProviderStatus2["NOT_READY"] = "NOT_READY"; | ||
ProviderStatus2["READY"] = "READY"; | ||
ProviderStatus2["ERROR"] = "ERROR"; | ||
return ProviderStatus2; | ||
})(ProviderStatus || {}); | ||
@@ -630,2 +636,72 @@ // ../shared/src/errors/open-feature-error-abstract.ts | ||
// ../shared/src/events.ts | ||
var import_events = __toESM(require_events()); | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var OpenFeatureEventEmitter = class { | ||
constructor(globalLogger) { | ||
this.globalLogger = globalLogger; | ||
this._handlers = /* @__PURE__ */ new WeakMap(); | ||
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); | ||
}); | ||
} | ||
emit(eventType, context) { | ||
this.eventEmitter.emit(eventType, context); | ||
} | ||
addHandler(eventType, handler) { | ||
const asyncHandler = (context) => __async(this, null, function* () { | ||
yield handler(context); | ||
}); | ||
this._handlers.set(handler, asyncHandler); | ||
this.eventEmitter.on(eventType, asyncHandler); | ||
} | ||
removeHandler(eventType, handler) { | ||
const asyncHandler = this._handlers.get(handler); | ||
if (!asyncHandler) { | ||
return; | ||
} | ||
this.eventEmitter.removeListener(eventType, asyncHandler); | ||
} | ||
removeAllHandlers(eventType) { | ||
if (eventType) { | ||
this.eventEmitter.removeAllListeners(eventType); | ||
} else { | ||
this.eventEmitter.removeAllListeners(); | ||
} | ||
} | ||
getHandlers(eventType) { | ||
return this.eventEmitter.listeners(eventType); | ||
} | ||
setLogger(logger) { | ||
this._eventLogger = new SafeLogger(logger); | ||
return this; | ||
} | ||
get _logger() { | ||
var _a; | ||
return this._eventLogger || ((_a = this.globalLogger) == null ? void 0 : _a.call(this)); | ||
} | ||
}; | ||
// ../shared/src/type-guards.ts | ||
function isString(value) { | ||
return typeof value === "string"; | ||
} | ||
function stringOrUndefined(value) { | ||
return isString(value) ? value : void 0; | ||
} | ||
function isObject(value) { | ||
return typeof value === "object"; | ||
} | ||
function objectOrUndefined(value) { | ||
return isObject(value) ? value : void 0; | ||
} | ||
// ../shared/src/open-feature.ts | ||
@@ -637,6 +713,137 @@ var OpenFeatureCommonAPI = class { | ||
this._logger = new DefaultLogger(); | ||
this._events = new OpenFeatureEventEmitter(() => this._logger); | ||
this._clientProviders = /* @__PURE__ */ new Map(); | ||
this._clientEvents = /* @__PURE__ */ new Map(); | ||
} | ||
setLogger(logger) { | ||
this._logger = new SafeLogger(logger); | ||
return this; | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._defaultProvider.metadata; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* When changing the provider, the currently attached handlers will listen to the events of the new provider. | ||
* @param {ProviderEvents} eventType The provider event type to listen to | ||
* @param {EventHandler} handler The handler to run on occurrence of the event type | ||
*/ | ||
addHandler(eventType, handler) { | ||
this._events.addHandler(eventType, handler); | ||
} | ||
/** | ||
* Removes a handler for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to remove the listener for | ||
* @param {EventHandler} handler The handler to remove for the provider event type | ||
*/ | ||
removeHandler(eventType, handler) { | ||
this._events.removeHandler(eventType, handler); | ||
} | ||
/** | ||
* Gets the current handlers for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to get the current handlers for | ||
* @returns {EventHandler[]} The handlers currently attached to the given provider event type | ||
*/ | ||
getHandlers(eventType) { | ||
return this._events.getHandlers(eventType); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
var _a, _b, _c, _d, _e, _f; | ||
const clientName = stringOrUndefined(clientOrProvider); | ||
const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined); | ||
if (!provider) { | ||
return this; | ||
} | ||
const oldProvider = this.getProviderForClient(clientName); | ||
if (oldProvider === provider) { | ||
return this; | ||
} | ||
const clientEmitter = this.getEventEmitterForClient(clientName); | ||
if (typeof provider.initialize === "function") { | ||
(_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => { | ||
var _a2; | ||
clientEmitter.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
})) == null ? void 0 : _d.catch((error) => { | ||
var _a2; | ||
clientEmitter.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message }); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, message: error.message }); | ||
}); | ||
} else { | ||
clientEmitter.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
(_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName }); | ||
} | ||
if (clientName) { | ||
this._clientProviders.set(clientName, provider); | ||
} else { | ||
this._defaultProvider = provider; | ||
} | ||
this.transferListeners(oldProvider, provider, clientName, clientEmitter); | ||
if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) { | ||
(_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider); | ||
} | ||
return this; | ||
} | ||
getProviderForClient(name) { | ||
var _a; | ||
if (!name) { | ||
return this._defaultProvider; | ||
} | ||
return (_a = this._clientProviders.get(name)) != null ? _a : this._defaultProvider; | ||
} | ||
getEventEmitterForClient(name) { | ||
const emitter = this._clientEvents.get(name); | ||
if (emitter) { | ||
return emitter; | ||
} | ||
const newEmitter = new OpenFeatureEventEmitter(() => this._logger); | ||
this._clientEvents.set(name, newEmitter); | ||
return newEmitter; | ||
} | ||
transferListeners(oldProvider, newProvider, clientName, clientEmitter) { | ||
var _a; | ||
(_a = oldProvider.events) == null ? void 0 : _a.removeAllHandlers(); | ||
Object.values(ProviderEvents).forEach( | ||
(eventType) => { | ||
var _a2; | ||
return (_a2 = newProvider.events) == null ? void 0 : _a2.addHandler(eventType, (details) => __async(this, null, function* () { | ||
clientEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName })); | ||
this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName })); | ||
})); | ||
} | ||
); | ||
} | ||
close() { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
try { | ||
yield (_b = (_a = this == null ? void 0 : this._defaultProvider) == null ? void 0 : _a.onClose) == null ? void 0 : _b.call(_a); | ||
} catch (err) { | ||
this.handleShutdownError(this._defaultProvider, err); | ||
} | ||
const providers = Array.from(this._clientProviders); | ||
yield Promise.all( | ||
providers.map((_0) => __async(this, [_0], function* ([, provider]) { | ||
var _a2; | ||
try { | ||
yield (_a2 = provider.onClose) == null ? void 0 : _a2.call(provider); | ||
} catch (err) { | ||
this.handleShutdownError(this._defaultProvider, err); | ||
} | ||
})) | ||
); | ||
}); | ||
} | ||
handleShutdownError(provider, err) { | ||
this._logger.error(`Error during shutdown of provider ${provider.metadata.name}: ${err}`); | ||
this._logger.error(err == null ? void 0 : err.stack); | ||
} | ||
setTransactionContextPropagator(transactionContextPropagator) { | ||
@@ -676,2 +883,5 @@ const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
} | ||
get status() { | ||
return "NOT_READY" /* NOT_READY */; | ||
} | ||
resolveBooleanEvaluation(_, defaultValue) { | ||
@@ -698,18 +908,4 @@ return this.noOp(defaultValue); | ||
// src/types.ts | ||
var import_events = __toESM(require_events()); | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents2) => { | ||
ProviderEvents2["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents2["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents2["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents2["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents2; | ||
})(ProviderEvents || {}); | ||
var ApiEvents = /* @__PURE__ */ ((ApiEvents2) => { | ||
ApiEvents2["ProviderChanged"] = "providerChanged"; | ||
return ApiEvents2; | ||
})(ApiEvents || {}); | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js.api"); | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/web-sdk/api"); | ||
var _globalThis = globalThis; | ||
@@ -720,10 +916,7 @@ var OpenFeatureAPI = class extends OpenFeatureCommonAPI { | ||
super(); | ||
this._apiEvents = new import_events.EventEmitter(); | ||
this._providerReady = false; | ||
this._hooks = []; | ||
this._provider = NOOP_PROVIDER; | ||
this._defaultProvider = NOOP_PROVIDER; | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* | ||
* @ignore | ||
@@ -741,10 +934,2 @@ * @returns {OpenFeatureAPI} OpenFeature API | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._provider.metadata; | ||
} | ||
setLogger(logger) { | ||
@@ -770,38 +955,16 @@ this._logger = new SafeLogger(logger); | ||
this._context = context; | ||
yield (_b = (_a = this._provider) == null ? void 0 : _a.onContextChange) == null ? void 0 : _b.call(_a, oldContext, context); | ||
yield (_b = (_a = this._defaultProvider) == null ? void 0 : _a.onContextChange) == null ? void 0 : _b.call(_a, oldContext, context); | ||
}); | ||
} | ||
setProvider(provider) { | ||
var _a, _b, _c, _d, _e, _f, _g; | ||
if (this._provider !== provider) { | ||
const oldProvider = this._provider; | ||
this._provider = provider; | ||
this._providerReady = false; | ||
if (!this._provider.events) { | ||
this._provider.events = new import_events.EventEmitter(); | ||
} | ||
if (typeof ((_a = this._provider) == null ? void 0 : _a.initialize) === "function") { | ||
(_e = (_d = (_c = (_b = this._provider).initialize) == null ? void 0 : _c.call(_b, this._context)) == null ? void 0 : _d.then(() => { | ||
var _a2; | ||
this._providerReady = true; | ||
(_a2 = this._provider.events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */); | ||
})) == null ? void 0 : _e.catch(() => { | ||
var _a2; | ||
(_a2 = this._provider.events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */); | ||
}); | ||
} else { | ||
this._providerReady = true; | ||
(_f = this._provider.events) == null ? void 0 : _f.emit("PROVIDER_READY" /* Ready */); | ||
} | ||
this._apiEvents.emit("providerChanged" /* ProviderChanged */); | ||
(_g = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _g.call(oldProvider); | ||
} | ||
return this; | ||
} | ||
close() { | ||
return __async(this, null, function* () { | ||
var _a, _b; | ||
yield (_b = (_a = this == null ? void 0 : this._provider) == null ? void 0 : _a.onClose) == null ? void 0 : _b.call(_a); | ||
}); | ||
} | ||
/** | ||
* 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} name The name of the client | ||
* @param {string} version The version of the client (only used for metadata) | ||
* @returns {Client} OpenFeature Client | ||
*/ | ||
getClient(name, version) { | ||
@@ -811,5 +974,4 @@ return new OpenFeatureClient( | ||
// and so we don't have to make these public properties on the API class. | ||
() => this._provider, | ||
() => this._providerReady, | ||
() => this._apiEvents, | ||
() => this.getProviderForClient(name), | ||
() => this.getEventEmitterForClient(name), | ||
() => this._logger, | ||
@@ -824,23 +986,29 @@ { name, version } | ||
var OpenFeatureClient = class { | ||
constructor(providerAccessor, providerReady, apiEvents, globalLogger, options) { | ||
constructor(providerAccessor, events, globalLogger, options) { | ||
this.providerAccessor = providerAccessor; | ||
this.providerReady = providerReady; | ||
this.events = events; | ||
this.globalLogger = globalLogger; | ||
this.options = options; | ||
this._hooks = []; | ||
this._handlerWrappers = []; | ||
this.metadata = { | ||
name: options.name, | ||
version: options.version | ||
} | ||
get metadata() { | ||
return { | ||
name: this.options.name, | ||
version: this.options.version, | ||
providerMetadata: this.providerAccessor().metadata | ||
}; | ||
this.attachListeners(); | ||
apiEvents().on("providerChanged" /* ProviderChanged */, () => { | ||
this.attachListeners(); | ||
}); | ||
} | ||
addHandler(eventType, handler) { | ||
this._handlerWrappers.push({ eventType, handler }); | ||
if (eventType === "PROVIDER_READY" /* Ready */ && this.providerReady()) { | ||
handler(); | ||
this.events().addHandler(eventType, handler); | ||
const providerReady = !this._provider.status || this._provider.status === "READY" /* READY */; | ||
if (eventType === "PROVIDER_READY" /* Ready */ && providerReady) { | ||
handler({ clientName: this.metadata.name }); | ||
} | ||
} | ||
removeHandler(notificationType, handler) { | ||
this.events().removeHandler(notificationType, handler); | ||
} | ||
getHandlers(eventType) { | ||
return this.events().getHandlers(eventType); | ||
} | ||
setLogger(logger) { | ||
@@ -865,9 +1033,3 @@ this._clientLogger = new SafeLogger(logger); | ||
getBooleanDetails(flagKey, defaultValue, options) { | ||
return this.evaluate( | ||
flagKey, | ||
this._provider.resolveBooleanEvaluation, | ||
defaultValue, | ||
"boolean", | ||
options | ||
); | ||
return this.evaluate(flagKey, this._provider.resolveBooleanEvaluation, defaultValue, "boolean", options); | ||
} | ||
@@ -907,2 +1069,3 @@ getStringValue(flagKey, defaultValue, options) { | ||
evaluate(flagKey, resolver, defaultValue, flagType, options = {}) { | ||
var _a; | ||
const allHooks = [ | ||
@@ -929,2 +1092,3 @@ ...OpenFeature.getHooks(), | ||
const evaluationDetails = __spreadProps(__spreadValues({}, resolution), { | ||
flagMetadata: Object.freeze((_a = resolution.flagMetadata) != null ? _a : {}), | ||
flagKey | ||
@@ -943,2 +1107,3 @@ }); | ||
reason: StandardResolutionReasons.ERROR, | ||
flagMetadata: Object.freeze({}), | ||
flagKey | ||
@@ -998,14 +1163,4 @@ }; | ||
} | ||
attachListeners() { | ||
Object.values(ProviderEvents).forEach((eventType) => { | ||
var _a; | ||
return (_a = this._provider.events) == null ? void 0 : _a.on(eventType, () => { | ||
this._handlerWrappers.filter((wrapper) => wrapper.eventType === eventType).forEach((wrapper) => wrapper.handler()); | ||
}); | ||
}); | ||
} | ||
}; | ||
var export_OpenFeatureEventEmitter = import_events.EventEmitter; | ||
export { | ||
ApiEvents, | ||
DefaultLogger, | ||
@@ -1023,5 +1178,6 @@ ErrorCode, | ||
OpenFeatureError, | ||
export_OpenFeatureEventEmitter as OpenFeatureEventEmitter, | ||
OpenFeatureEventEmitter, | ||
ParseError, | ||
ProviderEvents, | ||
ProviderStatus, | ||
SafeLogger, | ||
@@ -1028,0 +1184,0 @@ StandardResolutionReasons, |
@@ -0,1 +1,65 @@ | ||
type EventMetadata = { | ||
[key: string]: string | boolean | number; | ||
}; | ||
type EventDetails = { | ||
clientName?: string; | ||
message?: string; | ||
flagsChanged?: string[]; | ||
metadata?: EventMetadata; | ||
}; | ||
type EventHandler = (eventDetails?: EventDetails) => Promise<unknown> | unknown; | ||
interface Eventing { | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* @param {ProviderEvents} eventType The provider event type to listen to | ||
* @param {EventHandler} handler The handler to run on occurrence of the event type | ||
*/ | ||
addHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
/** | ||
* Removes a handler for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to remove the listener for | ||
* @param {EventHandler} handler The handler to remove for the provider event type | ||
*/ | ||
removeHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
/** | ||
* Gets the current handlers for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to get the current handlers for | ||
* @returns {EventHandler[]} The handlers currently attached to the given provider event type | ||
*/ | ||
getHandlers(eventType: ProviderEvents): EventHandler[]; | ||
} | ||
declare enum ProviderEvents { | ||
/** | ||
* The provider is ready to evaluate flags. | ||
*/ | ||
Ready = "PROVIDER_READY", | ||
/** | ||
* The provider is in an error state. | ||
*/ | ||
Error = "PROVIDER_ERROR", | ||
/** | ||
* The flag configuration in the source-of-truth has changed. | ||
*/ | ||
ConfigurationChanged = "PROVIDER_CONFIGURATION_CHANGED", | ||
/** | ||
* The provider's cached state is no longer valid and may not be up-to-date with the source of truth. | ||
*/ | ||
Stale = "PROVIDER_STALE" | ||
} | ||
declare class OpenFeatureEventEmitter implements ManageLogger<OpenFeatureEventEmitter> { | ||
private readonly globalLogger?; | ||
private readonly _handlers; | ||
private readonly eventEmitter; | ||
private _eventLogger?; | ||
constructor(globalLogger?: (() => Logger) | undefined); | ||
emit(eventType: ProviderEvents, context?: EventDetails): void; | ||
addHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
removeHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
removeAllHandlers(eventType?: ProviderEvents): void; | ||
getHandlers(eventType: ProviderEvents): EventHandler[]; | ||
setLogger(logger: Logger): this; | ||
private get _logger(); | ||
} | ||
type PrimitiveValue = null | boolean | string | number; | ||
@@ -49,3 +113,3 @@ type JsonObject = { | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
@@ -103,5 +167,12 @@ readonly DEFAULT: "DEFAULT"; | ||
type ResolutionReason = keyof typeof StandardResolutionReasons | (string & Record<never, never>); | ||
/** | ||
* A structure which supports definition of arbitrary properties, with keys of type string, and values of type boolean, string, or number. | ||
* | ||
* This structure is populated by a provider for use by an Application Author (via the Evaluation API) or an Application Integrator (via hooks). | ||
*/ | ||
type FlagMetadata = Record<string, string | number | boolean>; | ||
type ResolutionDetails<U> = { | ||
value: U; | ||
variant?: string; | ||
flagMetadata?: FlagMetadata; | ||
reason?: ResolutionReason; | ||
@@ -113,2 +184,3 @@ errorCode?: ErrorCode; | ||
flagKey: string; | ||
flagMetadata: Readonly<FlagMetadata>; | ||
} & ResolutionDetails<T>; | ||
@@ -118,3 +190,2 @@ interface ManageContext<T> { | ||
* Access the evaluation context set on the receiver. | ||
* | ||
* @returns {EvaluationContext} Evaluation context | ||
@@ -126,3 +197,2 @@ */ | ||
* on this receiver. | ||
* | ||
* @template T The type of the receiver | ||
@@ -140,3 +210,2 @@ * @param {EvaluationContext} context Evaluation context | ||
* unless overridden in a particular client. | ||
* | ||
* @template T The type of the receiver | ||
@@ -154,2 +223,3 @@ * @param {Logger} logger The logger to be used | ||
readonly name?: string; | ||
readonly providerMetadata: ProviderMetadata; | ||
} | ||
@@ -185,3 +255,2 @@ interface ProviderMetadata extends Metadata { | ||
* transaction. | ||
* | ||
* @experimental | ||
@@ -201,3 +270,2 @@ * @template T The type of the receiver | ||
* context propagator. | ||
* | ||
* @experimental | ||
@@ -212,3 +280,2 @@ * @returns {TransactionContext} The current transaction context | ||
* Sets the transaction context using the registered transaction context propagator. | ||
* | ||
* @experimental | ||
@@ -222,4 +289,25 @@ * @template R The return value of the callback | ||
} | ||
declare enum ProviderStatus { | ||
NOT_READY = "NOT_READY", | ||
READY = "READY", | ||
ERROR = "ERROR" | ||
} | ||
interface CommonProvider { | ||
readonly metadata: ProviderMetadata; | ||
readonly status?: ProviderStatus; | ||
/** | ||
* An event emitter for ProviderEvents. | ||
* @see ProviderEvents | ||
*/ | ||
events?: OpenFeatureEventEmitter; | ||
onClose?(): Promise<void>; | ||
/** | ||
* A handler function used to setup the provider. | ||
* Called by the SDK after the provider is set. | ||
* When the returned promise resolves, the SDK fires the ProviderEvents.Ready event. | ||
* If the returned promise rejects, the SDK fires the ProviderEvents.Error event. | ||
* Use this function to perform any context-dependent setup within the provider. | ||
* @param context | ||
*/ | ||
initialize?(context?: EvaluationContext): Promise<void>; | ||
} | ||
@@ -285,79 +373,66 @@ | ||
declare abstract class OpenFeatureCommonAPI { | ||
declare abstract class OpenFeatureCommonAPI<P extends CommonProvider = CommonProvider> implements Eventing { | ||
protected _transactionContextPropagator: TransactionContextPropagator; | ||
protected _context: EvaluationContext; | ||
protected _logger: Logger; | ||
protected abstract _defaultProvider: P; | ||
private readonly _events; | ||
protected _clientProviders: Map<string, P>; | ||
protected _clientEvents: Map<string | undefined, OpenFeatureEventEmitter>; | ||
abstract clearHooks(): this; | ||
abstract setLogger(logger: Logger): this; | ||
setLogger(logger: Logger): this; | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata(): ProviderMetadata; | ||
getContext(): EvaluationContext; | ||
setTransactionContextPropagator(transactionContextPropagator: TransactionContextPropagator): OpenFeatureCommonAPI; | ||
setTransactionContext<R>(transactionContext: TransactionContext, callback: (...args: unknown[]) => R, ...args: unknown[]): void; | ||
getTransactionContext(): TransactionContext; | ||
} | ||
// Type definitions for events 3.0 | ||
// Project: https://github.com/Gozala/events | ||
// Definitions by: Yasunori Ohoka <https://github.com/yasupeke> | ||
// Shenwei Wang <https://github.com/weareoutman> | ||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped | ||
type Listener = (...args: any[]) => void; | ||
declare class EventEmitter { | ||
static listenerCount(emitter: EventEmitter, type: string | number): number; | ||
static defaultMaxListeners: number; | ||
eventNames(): Array<string | number>; | ||
setMaxListeners(n: number): this; | ||
getMaxListeners(): number; | ||
emit(type: string | number, ...args: any[]): boolean; | ||
addListener(type: string | number, listener: Listener): this; | ||
on(type: string | number, listener: Listener): this; | ||
once(type: string | number, listener: Listener): this; | ||
prependListener(type: string | number, listener: Listener): this; | ||
prependOnceListener(type: string | number, listener: Listener): this; | ||
removeListener(type: string | number, listener: Listener): this; | ||
off(type: string | number, listener: Listener): this; | ||
removeAllListeners(type?: string | number): this; | ||
listeners(type: string | number): Listener[]; | ||
listenerCount(type: string | number): number; | ||
rawListeners(type: string | number): Listener[]; | ||
} | ||
declare enum ProviderEvents { | ||
/** | ||
* The provider is ready to evaluate flags. | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* When changing the provider, the currently attached handlers will listen to the events of the new provider. | ||
* @param {ProviderEvents} eventType The provider event type to listen to | ||
* @param {EventHandler} handler The handler to run on occurrence of the event type | ||
*/ | ||
Ready = "PROVIDER_READY", | ||
addHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
/** | ||
* The provider is in an error state. | ||
* Removes a handler for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to remove the listener for | ||
* @param {EventHandler} handler The handler to remove for the provider event type | ||
*/ | ||
Error = "PROVIDER_ERROR", | ||
removeHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
/** | ||
* The flag configuration in the source-of-truth has changed. | ||
* Gets the current handlers for the given provider event type. | ||
* @param {ProviderEvents} eventType The provider event type to get the current handlers for | ||
* @returns {EventHandler[]} The handlers currently attached to the given provider event type | ||
*/ | ||
ConfigurationChanged = "PROVIDER_CONFIGURATION_CHANGED", | ||
getHandlers(eventType: ProviderEvents): EventHandler[]; | ||
/** | ||
* The provider's cached state is not longer valid and may not be up-to-date with the source of truth. | ||
* Sets the default provider for flag evaluations. | ||
* This provider will be used by unnamed clients and named clients to which no provider is bound. | ||
* Setting a provider supersedes the current provider used in new and existing clients without a name. | ||
* @template P | ||
* @param {P} provider The provider responsible for flag evaluations. | ||
* @returns {OpenFeatureCommonAPI} OpenFeature API | ||
*/ | ||
Stale = "PROVIDER_STALE" | ||
setProvider(provider: P): this; | ||
/** | ||
* Sets the provider that OpenFeature will use for flag evaluations of providers with the given name. | ||
* Setting a provider supersedes the current provider used in new and existing clients with that name. | ||
* @template P | ||
* @param {string} clientName The name to identify the client | ||
* @param {P} provider The provider responsible for flag evaluations. | ||
* @returns {this} OpenFeature API | ||
*/ | ||
setProvider(clientName: string, provider: P): this; | ||
protected getProviderForClient(name?: string): P; | ||
protected getEventEmitterForClient(name?: string): OpenFeatureEventEmitter; | ||
private transferListeners; | ||
close(): Promise<void>; | ||
private handleShutdownError; | ||
setTransactionContextPropagator(transactionContextPropagator: TransactionContextPropagator): OpenFeatureCommonAPI<P>; | ||
setTransactionContext<R>(transactionContext: TransactionContext, callback: (...args: unknown[]) => R, ...args: unknown[]): void; | ||
getTransactionContext(): TransactionContext; | ||
} | ||
interface EventData { | ||
flagKeysChanged?: string[]; | ||
changeMetadata?: { | ||
[key: string]: boolean | string; | ||
}; | ||
} | ||
declare enum ApiEvents { | ||
ProviderChanged = "providerChanged" | ||
} | ||
interface Eventing { | ||
addHandler(notificationType: string, handler: Handler): void; | ||
} | ||
type EventContext = { | ||
notificationType: string; | ||
[key: string]: unknown; | ||
}; | ||
type Handler = (eventContext?: EventContext) => void; | ||
type EventCallbackMessage = (eventContext: EventContext) => void; | ||
/** | ||
@@ -378,11 +453,4 @@ * Interface that providers must implement to resolve flag values for their particular | ||
/** | ||
* An event emitter for ProviderEvents. | ||
* | ||
* @see ProviderEvents | ||
*/ | ||
events?: EventEmitter; | ||
/** | ||
* A handler function to reconcile changes when the static context. | ||
* Called by the SDK when the context is changed. | ||
* | ||
* @param oldContext | ||
@@ -392,14 +460,3 @@ * @param newContext | ||
onContextChange?(oldContext: EvaluationContext, newContext: EvaluationContext): Promise<void>; | ||
onClose?(): Promise<void>; | ||
/** | ||
* A handler function used to setup the provider. | ||
* Called by the SDK after the provider is set. | ||
* When the returned promise resolves, the SDK fires the ProviderEvents.Ready event. | ||
* If the returned promise rejects, the SDK fires the ProviderEvents.Error event. | ||
* Use this function to perform any context-dependent setup within the provider. | ||
* | ||
* @param context | ||
*/ | ||
initialize?(context: EvaluationContext): Promise<void>; | ||
/** | ||
* Resolve a boolean flag and its evaluation details. | ||
@@ -425,3 +482,2 @@ */ | ||
* If an EvaluationContext is returned, it will be merged with the pre-existing EvaluationContext. | ||
* | ||
* @param hookContext | ||
@@ -433,3 +489,2 @@ * @param hookHints | ||
* Runs after flag values are successfully resolved from the provider. | ||
* | ||
* @param hookContext | ||
@@ -442,3 +497,2 @@ * @param evaluationDetails | ||
* Runs in the event of an unhandled error or promise rejection during flag resolution, or any attached hooks. | ||
* | ||
* @param hookContext | ||
@@ -452,3 +506,2 @@ * @param error | ||
* Errors thrown here are unhandled by the client and will surface in application code. | ||
* | ||
* @param hookContext | ||
@@ -466,3 +519,2 @@ * @param hookHints | ||
* Hooks registered on the client run with all evaluations on that client. | ||
* | ||
* @template T The type of the receiver | ||
@@ -475,3 +527,2 @@ * @param {Hook<FlagValue>[]} hooks A list of hooks that should always run | ||
* Access all the hooks that are registered on this receiver. | ||
* | ||
* @returns {Hook<FlagValue>[]} A list of the client hooks | ||
@@ -482,3 +533,2 @@ */ | ||
* Clears all the hooks that are registered on this receiver. | ||
* | ||
* @template T The type of the receiver | ||
@@ -496,3 +546,2 @@ * @returns {T} The receiver (this object) | ||
* Performs a flag evaluation that returns a boolean. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -506,3 +555,2 @@ * @param {boolean} defaultValue The value returned if an error occurs | ||
* Performs a flag evaluation that a returns an evaluation details object. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -516,3 +564,2 @@ * @param {boolean} defaultValue The value returned if an error occurs | ||
* Performs a flag evaluation that returns a string. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -528,3 +575,2 @@ * @template {string} T A optional generic argument constraining the string | ||
* Performs a flag evaluation that a returns an evaluation details object. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -540,3 +586,2 @@ * @template {string} T A optional generic argument constraining the string | ||
* Performs a flag evaluation that returns a number. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -552,3 +597,2 @@ * @template {number} T A optional generic argument constraining the number | ||
* Performs a flag evaluation that a returns an evaluation details object. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -564,3 +608,2 @@ * @template {number} T A optional generic argument constraining the number | ||
* Performs a flag evaluation that returns an object. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -576,3 +619,2 @@ * @template {JsonValue} T A optional generic argument describing the structure | ||
* Performs a flag evaluation that a returns an evaluation details object. | ||
* | ||
* @param {string} flagKey The flag key uniquely identifies a particular flag | ||
@@ -596,3 +638,2 @@ * @template {JsonValue} T A optional generic argument describing the structure | ||
* to segment feature flag configuration. | ||
* | ||
* @param {string} name The name of the client | ||
@@ -607,3 +648,2 @@ * @param {string} version The version of the client | ||
* a provider supersedes the current provider used in new and existing clients. | ||
* | ||
* @param {Provider} provider The provider responsible for flag evaluations. | ||
@@ -621,10 +661,12 @@ * @returns {GlobalApi} OpenFeature API | ||
private readonly providerAccessor; | ||
private readonly providerReady; | ||
private readonly events; | ||
private readonly globalLogger; | ||
readonly metadata: ClientMetadata; | ||
private readonly options; | ||
private _hooks; | ||
private _clientLogger?; | ||
private _handlerWrappers; | ||
constructor(providerAccessor: () => Provider, providerReady: () => boolean, apiEvents: () => EventEmitter, globalLogger: () => Logger, options: OpenFeatureClientOptions); | ||
addHandler(eventType: ProviderEvents, handler: Handler): void; | ||
constructor(providerAccessor: () => Provider, events: () => OpenFeatureEventEmitter, globalLogger: () => Logger, options: OpenFeatureClientOptions); | ||
get metadata(): ClientMetadata; | ||
addHandler(eventType: ProviderEvents, handler: EventHandler): void; | ||
removeHandler(notificationType: ProviderEvents, handler: EventHandler): void; | ||
getHandlers(eventType: ProviderEvents): EventHandler[]; | ||
setLogger(logger: Logger): OpenFeatureClient; | ||
@@ -649,3 +691,2 @@ addHooks(...hooks: Hook<FlagValue>[]): OpenFeatureClient; | ||
private get _logger(); | ||
private attachListeners; | ||
} | ||
@@ -660,2 +701,3 @@ | ||
}; | ||
get status(): ProviderStatus; | ||
resolveBooleanEvaluation(_: string, defaultValue: boolean): ResolutionDetails<boolean>; | ||
@@ -669,11 +711,8 @@ resolveStringEvaluation(_: string, defaultValue: string): ResolutionDetails<string>; | ||
declare class OpenFeatureAPI extends OpenFeatureCommonAPI { | ||
private _apiEvents; | ||
private _providerReady; | ||
declare class OpenFeatureAPI extends OpenFeatureCommonAPI<Provider> { | ||
protected _hooks: Hook[]; | ||
protected _provider: Provider; | ||
protected _defaultProvider: Provider; | ||
private constructor(); | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* | ||
* @ignore | ||
@@ -683,8 +722,2 @@ * @returns {OpenFeatureAPI} OpenFeature API | ||
static getInstance(): OpenFeatureAPI; | ||
/** | ||
* Get metadata about registered provider. | ||
* | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata(): ProviderMetadata; | ||
setLogger(logger: Logger): this; | ||
@@ -695,4 +728,13 @@ addHooks(...hooks: Hook<FlagValue>[]): this; | ||
setContext(context: EvaluationContext): Promise<void>; | ||
setProvider(provider: Provider): OpenFeatureCommonAPI; | ||
close(): Promise<void>; | ||
/** | ||
* 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} name The name of the client | ||
* @param {string} version The version of the client (only used for metadata) | ||
* @returns {Client} OpenFeature Client | ||
*/ | ||
getClient(name?: string, version?: string): Client; | ||
@@ -702,3 +744,2 @@ } | ||
* A singleton instance of the OpenFeature API. | ||
* | ||
* @returns {OpenFeatureAPI} OpenFeature API | ||
@@ -708,2 +749,2 @@ */ | ||
export { ApiEvents, BeforeHookContext, Client, ClientMetadata, CommonProvider, DefaultLogger, ErrorCode, EvaluationContext, EvaluationContextValue, EvaluationDetails, EventCallbackMessage, EventContext, EventData, Eventing, Features, FlagEvaluationOptions, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GlobalApi, Handler, Hook, HookContext, HookHints, InvalidContextError, JsonArray, JsonObject, JsonValue, Logger, ManageContext, ManageLogger, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, EventEmitter as OpenFeatureEventEmitter, ParseError, PrimitiveValue, Provider, ProviderEvents, ProviderMetadata, ResolutionDetails, ResolutionReason, SafeLogger, StandardResolutionReasons, TargetingKeyMissingError, TransactionContext, TransactionContextPropagator, TypeMismatchError }; | ||
export { BeforeHookContext, Client, ClientMetadata, CommonProvider, DefaultLogger, ErrorCode, EvaluationContext, EvaluationContextValue, EvaluationDetails, EventDetails, EventHandler, EventMetadata, Eventing, Features, FlagEvaluationOptions, FlagMetadata, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GlobalApi, Hook, HookContext, HookHints, InvalidContextError, JsonArray, JsonObject, JsonValue, Logger, ManageContext, ManageLogger, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, OpenFeatureEventEmitter, ParseError, PrimitiveValue, Provider, ProviderEvents, ProviderMetadata, ProviderStatus, ResolutionDetails, ResolutionReason, SafeLogger, StandardResolutionReasons, TargetingKeyMissingError, TransactionContext, TransactionContextPropagator, TypeMismatchError }; |
{ | ||
"name": "@openfeature/web-sdk", | ||
"version": "0.3.2-experimental", | ||
"version": "0.3.3-experimental", | ||
"description": "OpenFeature SDK for Web", | ||
@@ -49,3 +49,3 @@ "main": "./dist/cjs/index.js", | ||
"devDependencies": { | ||
"@openfeature/shared": "0.0.3" | ||
"@openfeature/shared": "*" | ||
}, | ||
@@ -52,0 +52,0 @@ "typedoc": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
290400
2989