@openfeature/server-sdk
Advanced tools
Comparing version 1.6.3 to 1.7.0
"use strict"; | ||
var __create = Object.create; | ||
var __defProp = Object.defineProperty; | ||
@@ -9,3 +8,2 @@ var __defProps = Object.defineProperties; | ||
var __getOwnPropSymbols = Object.getOwnPropertySymbols; | ||
var __getProtoOf = Object.getPrototypeOf; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
@@ -38,10 +36,3 @@ var __propIsEnum = Object.prototype.propertyIsEnumerable; | ||
}; | ||
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default")); | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
@@ -72,10 +63,3 @@ var __async = (__this, __arguments, generator) => { | ||
__export(src_exports, { | ||
DefaultLogger: () => DefaultLogger, | ||
ErrorCode: () => ErrorCode, | ||
FlagNotFoundError: () => FlagNotFoundError, | ||
GeneralError: () => GeneralError, | ||
InMemoryProvider: () => InMemoryProvider, | ||
InternalEventEmitter: () => InternalEventEmitter, | ||
InvalidContextError: () => InvalidContextError, | ||
LOG_LEVELS: () => LOG_LEVELS, | ||
NOOP_PROVIDER: () => NOOP_PROVIDER, | ||
@@ -85,564 +69,11 @@ NOOP_TRANSACTION_CONTEXT_PROPAGATOR: () => NOOP_TRANSACTION_CONTEXT_PROPAGATOR, | ||
OpenFeatureAPI: () => OpenFeatureAPI, | ||
OpenFeatureClient: () => OpenFeatureClient, | ||
OpenFeatureCommonAPI: () => OpenFeatureCommonAPI, | ||
OpenFeatureError: () => OpenFeatureError, | ||
OpenFeatureEventEmitter: () => OpenFeatureEventEmitter, | ||
ParseError: () => ParseError, | ||
ProviderEvents: () => ProviderEvents, | ||
ProviderStatus: () => ProviderStatus, | ||
SafeLogger: () => SafeLogger, | ||
StandardResolutionReasons: () => StandardResolutionReasons, | ||
TargetingKeyMissingError: () => TargetingKeyMissingError, | ||
TypeMismatchError: () => TypeMismatchError, | ||
isObject: () => isObject, | ||
isString: () => isString, | ||
objectOrUndefined: () => objectOrUndefined, | ||
statusMatchesEvent: () => statusMatchesEvent, | ||
stringOrUndefined: () => stringOrUndefined | ||
OpenFeatureClient: () => OpenFeatureClient | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
// ../shared/src/errors/open-feature-error-abstract.ts | ||
var OpenFeatureError = class extends Error { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, OpenFeatureError.prototype); | ||
this.name = "OpenFeatureError"; | ||
} | ||
}; | ||
// src/client/open-feature-client.ts | ||
var import_core5 = require("@openfeature/core"); | ||
// ../shared/src/evaluation/evaluation.ts | ||
var StandardResolutionReasons = { | ||
/** | ||
* The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. | ||
*/ | ||
TARGETING_MATCH: "TARGETING_MATCH", | ||
/** | ||
* The resolved value was the result of pseudorandom assignment. | ||
*/ | ||
SPLIT: "SPLIT", | ||
/** | ||
* The resolved value was the result of the flag being disabled in the management system. | ||
*/ | ||
DISABLED: "DISABLED", | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
DEFAULT: "DEFAULT", | ||
/** | ||
* The reason for the resolved value could not be determined. | ||
*/ | ||
UNKNOWN: "UNKNOWN", | ||
/** | ||
* The resolved value is static (no dynamic evaluation). | ||
*/ | ||
STATIC: "STATIC", | ||
/** | ||
* The resolved value was retrieved from cache. | ||
*/ | ||
CACHED: "CACHED", | ||
/** | ||
* The resolved value was the result of an error. | ||
* | ||
* Note: The `errorCode` and `errorMessage` fields may contain additional details of this error. | ||
*/ | ||
ERROR: "ERROR" | ||
}; | ||
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { | ||
ErrorCode2["PROVIDER_NOT_READY"] = "PROVIDER_NOT_READY"; | ||
ErrorCode2["FLAG_NOT_FOUND"] = "FLAG_NOT_FOUND"; | ||
ErrorCode2["PARSE_ERROR"] = "PARSE_ERROR"; | ||
ErrorCode2["TYPE_MISMATCH"] = "TYPE_MISMATCH"; | ||
ErrorCode2["TARGETING_KEY_MISSING"] = "TARGETING_KEY_MISSING"; | ||
ErrorCode2["INVALID_CONTEXT"] = "INVALID_CONTEXT"; | ||
ErrorCode2["GENERAL"] = "GENERAL"; | ||
return ErrorCode2; | ||
})(ErrorCode || {}); | ||
// ../shared/src/errors/general-error.ts | ||
var GeneralError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, GeneralError.prototype); | ||
this.name = "GeneralError"; | ||
this.code = "GENERAL" /* GENERAL */; | ||
} | ||
}; | ||
// ../shared/src/errors/flag-not-found-error.ts | ||
var FlagNotFoundError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, FlagNotFoundError.prototype); | ||
this.name = "FlagNotFoundError"; | ||
this.code = "FLAG_NOT_FOUND" /* FLAG_NOT_FOUND */; | ||
} | ||
}; | ||
// ../shared/src/errors/parse-error.ts | ||
var ParseError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, ParseError.prototype); | ||
this.name = "ParseError"; | ||
this.code = "PARSE_ERROR" /* PARSE_ERROR */; | ||
} | ||
}; | ||
// ../shared/src/errors/type-mismatch-error.ts | ||
var TypeMismatchError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, TypeMismatchError.prototype); | ||
this.name = "TypeMismatchError"; | ||
this.code = "TYPE_MISMATCH" /* TYPE_MISMATCH */; | ||
} | ||
}; | ||
// ../shared/src/errors/targeting-key-missing-error.ts | ||
var TargetingKeyMissingError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, TargetingKeyMissingError.prototype); | ||
this.name = "TargetingKeyMissingError"; | ||
this.code = "TARGETING_KEY_MISSING" /* TARGETING_KEY_MISSING */; | ||
} | ||
}; | ||
// ../shared/src/errors/invalid-context-error.ts | ||
var InvalidContextError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, InvalidContextError.prototype); | ||
this.name = "InvalidContextError"; | ||
this.code = "INVALID_CONTEXT" /* INVALID_CONTEXT */; | ||
} | ||
}; | ||
// ../shared/src/provider/provider.ts | ||
var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => { | ||
ProviderStatus2["NOT_READY"] = "NOT_READY"; | ||
ProviderStatus2["READY"] = "READY"; | ||
ProviderStatus2["ERROR"] = "ERROR"; | ||
ProviderStatus2["STALE"] = "STALE"; | ||
return ProviderStatus2; | ||
})(ProviderStatus || {}); | ||
// ../shared/src/events/events.ts | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents3) => { | ||
ProviderEvents3["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents3["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents3["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents3["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents3; | ||
})(ProviderEvents || {}); | ||
// ../shared/src/events/event-utils.ts | ||
var eventStatusMap = { | ||
["READY" /* READY */]: "PROVIDER_READY" /* Ready */, | ||
["ERROR" /* ERROR */]: "PROVIDER_ERROR" /* Error */, | ||
["STALE" /* STALE */]: "PROVIDER_STALE" /* Stale */, | ||
["NOT_READY" /* NOT_READY */]: void 0 | ||
}; | ||
var statusMatchesEvent = (event, status) => { | ||
return !status && event === "PROVIDER_READY" /* Ready */ || eventStatusMap[status] === event; | ||
}; | ||
// ../shared/src/events/open-feature-event-emitter.ts | ||
var import_events2 = __toESM(require("events")); | ||
// ../shared/src/logger/default-logger.ts | ||
var DefaultLogger = class { | ||
error(...args) { | ||
console.error(...args); | ||
} | ||
warn(...args) { | ||
console.warn(...args); | ||
} | ||
info() { | ||
} | ||
debug() { | ||
} | ||
}; | ||
// ../shared/src/logger/safe-logger.ts | ||
var LOG_LEVELS = ["error", "warn", "info", "debug"]; | ||
var SafeLogger = class { | ||
constructor(logger) { | ||
this.fallbackLogger = new DefaultLogger(); | ||
try { | ||
for (const level of LOG_LEVELS) { | ||
if (!logger[level] || typeof logger[level] !== "function") { | ||
throw new Error(`The provided logger is missing the ${level} method.`); | ||
} | ||
} | ||
this.logger = logger; | ||
} catch (err) { | ||
console.error(err); | ||
console.error("Falling back to the default logger."); | ||
this.logger = this.fallbackLogger; | ||
} | ||
} | ||
error(...args) { | ||
this.log("error", ...args); | ||
} | ||
warn(...args) { | ||
this.log("warn", ...args); | ||
} | ||
info(...args) { | ||
this.log("info", ...args); | ||
} | ||
debug(...args) { | ||
this.log("debug", ...args); | ||
} | ||
log(level, ...args) { | ||
try { | ||
this.logger[level](...args); | ||
} catch (error) { | ||
this.fallbackLogger[level](...args); | ||
} | ||
} | ||
}; | ||
// ../shared/src/events/open-feature-event-emitter.ts | ||
var GenericEventEmitter = class { | ||
constructor(globalLogger) { | ||
this.globalLogger = globalLogger; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
this._handlers = /* @__PURE__ */ new WeakMap(); | ||
this.eventEmitter = new import_events2.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 = (details) => __async(this, null, function* () { | ||
yield handler(details); | ||
}); | ||
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, _b; | ||
return (_b = this._eventLogger) != null ? _b : (_a = this.globalLogger) == null ? void 0 : _a.call(this); | ||
} | ||
}; | ||
var OpenFeatureEventEmitter = class extends GenericEventEmitter { | ||
}; | ||
var InternalEventEmitter = class extends GenericEventEmitter { | ||
}; | ||
// ../shared/src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback) { | ||
callback(); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// ../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/filter.ts | ||
function isDefined(input) { | ||
return typeof input !== "undefined" && input !== null; | ||
} | ||
// ../shared/src/open-feature.ts | ||
var OpenFeatureCommonAPI = class { | ||
constructor(category) { | ||
this._hooks = []; | ||
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
this._context = {}; | ||
this._logger = new DefaultLogger(); | ||
this._events = new InternalEventEmitter(() => this._logger); | ||
this._clientEventHandlers = /* @__PURE__ */ new Map(); | ||
this._clientProviders = /* @__PURE__ */ new Map(); | ||
this._clientEvents = /* @__PURE__ */ new Map(); | ||
this._runsOn = category; | ||
} | ||
addHooks(...hooks) { | ||
this._hooks = [...this._hooks, ...hooks]; | ||
return this; | ||
} | ||
getHooks() { | ||
return this._hooks; | ||
} | ||
clearHooks() { | ||
this._hooks = []; | ||
return this; | ||
} | ||
setLogger(logger) { | ||
this._logger = new SafeLogger(logger); | ||
return this; | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._defaultProvider.metadata; | ||
} | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* API (global) events run for all providers. | ||
* @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) { | ||
[.../* @__PURE__ */ new Map([[void 0, this._defaultProvider]]), ...this._clientProviders].forEach((keyProviderTuple) => { | ||
var _a; | ||
const clientName = keyProviderTuple[0]; | ||
const provider = keyProviderTuple[1]; | ||
const shouldRunNow = statusMatchesEvent(eventType, keyProviderTuple[1].status); | ||
if (shouldRunNow) { | ||
try { | ||
handler({ clientName, providerName: provider.metadata.name }); | ||
} catch (err) { | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
} | ||
} | ||
}); | ||
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); | ||
} | ||
setProviderAndWait(clientOrProvider, providerOrUndefined) { | ||
return __async(this, null, function* () { | ||
yield this.setAwaitableProvider(clientOrProvider, providerOrUndefined); | ||
}); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
const maybePromise = this.setAwaitableProvider(clientOrProvider, providerOrUndefined); | ||
if (maybePromise) { | ||
maybePromise.catch(() => { | ||
}); | ||
} | ||
return this; | ||
} | ||
setAwaitableProvider(clientOrProvider, providerOrUndefined) { | ||
var _a, _b, _c, _d, _e, _f; | ||
const clientName = stringOrUndefined(clientOrProvider); | ||
const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined); | ||
if (!provider) { | ||
this._logger.debug("No provider defined, ignoring setProvider call"); | ||
return; | ||
} | ||
const oldProvider = this.getProviderForClient(clientName); | ||
const providerName = provider.metadata.name; | ||
if (oldProvider === provider) { | ||
this._logger.debug("Provider is already set, ignoring setProvider call"); | ||
return; | ||
} | ||
if (!provider.runsOn) { | ||
this._logger.debug(`Provider '${provider.metadata.name}' has not defined its intended use.`); | ||
} else if (provider.runsOn !== this._runsOn) { | ||
throw new GeneralError(`Provider '${provider.metadata.name}' is intended for use on the ${provider.runsOn}.`); | ||
} | ||
const emitters = this.getAssociatedEventEmitters(clientName); | ||
if (typeof provider.initialize === "function" && provider.status === void 0) { | ||
const activeLogger = this._logger || console; | ||
activeLogger.warn( | ||
`Provider ${providerName} implements 'initialize' but not 'status'. Please implement 'status'.` | ||
); | ||
} | ||
let initializationPromise = void 0; | ||
if ((provider == null ? void 0 : provider.status) === "NOT_READY" /* NOT_READY */ && typeof provider.initialize === "function") { | ||
initializationPromise = (_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => { | ||
var _a2; | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
}); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
})) == null ? void 0 : _d.catch((error) => { | ||
var _a2; | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message }); | ||
}); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message }); | ||
throw error; | ||
}); | ||
} else { | ||
emitters.forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
}); | ||
(_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
} | ||
if (clientName) { | ||
this._clientProviders.set(clientName, provider); | ||
} else { | ||
this._defaultProvider = provider; | ||
} | ||
this.transferListeners(oldProvider, provider, clientName, emitters); | ||
if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) { | ||
(_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider); | ||
} | ||
return initializationPromise; | ||
} | ||
getProviderForClient(name) { | ||
var _a; | ||
if (!name) { | ||
return this._defaultProvider; | ||
} | ||
return (_a = this._clientProviders.get(name)) != null ? _a : this._defaultProvider; | ||
} | ||
buildAndCacheEventEmitterForClient(name) { | ||
const emitter = this._clientEvents.get(name); | ||
if (emitter) { | ||
return emitter; | ||
} | ||
const newEmitter = new InternalEventEmitter(() => this._logger); | ||
this._clientEvents.set(name, newEmitter); | ||
const clientProvider = this.getProviderForClient(name); | ||
Object.values(ProviderEvents).forEach( | ||
(eventType) => { | ||
var _a; | ||
return (_a = clientProvider.events) == null ? void 0 : _a.addHandler(eventType, (details) => __async(this, null, function* () { | ||
newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name, providerName: clientProvider.metadata.name })); | ||
})); | ||
} | ||
); | ||
return newEmitter; | ||
} | ||
getUnboundEmitters() { | ||
const namedProviders = [...this._clientProviders.keys()]; | ||
const eventEmitterNames = [...this._clientEvents.keys()].filter(isDefined); | ||
const unboundEmitterNames = eventEmitterNames.filter((name) => !namedProviders.includes(name)); | ||
return [ | ||
// all unbound, named emitters | ||
...unboundEmitterNames.map((name) => this._clientEvents.get(name)), | ||
// the default emitter | ||
this._clientEvents.get(void 0) | ||
].filter(isDefined); | ||
} | ||
getAssociatedEventEmitters(clientName) { | ||
return clientName ? [this.buildAndCacheEventEmitterForClient(clientName)] : this.getUnboundEmitters(); | ||
} | ||
transferListeners(oldProvider, newProvider, clientName, emitters) { | ||
var _a; | ||
(_a = this._clientEventHandlers.get(clientName)) == null ? void 0 : _a.forEach((eventHandler) => { | ||
var _a2; | ||
return (_a2 = oldProvider.events) == null ? void 0 : _a2.removeHandler(...eventHandler); | ||
}); | ||
const newClientHandlers = Object.values(ProviderEvents).map((eventType) => { | ||
const handler = (details) => __async(this, null, function* () { | ||
emitters.forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name })); | ||
}); | ||
this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name })); | ||
}); | ||
return [eventType, handler]; | ||
}); | ||
this._clientEventHandlers.set(clientName, newClientHandlers); | ||
newClientHandlers.forEach((eventHandler) => { | ||
var _a2; | ||
return (_a2 = newProvider.events) == null ? void 0 : _a2.addHandler(...eventHandler); | ||
}); | ||
} | ||
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) { | ||
const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); | ||
} else { | ||
this._transactionContextPropagator = transactionContextPropagator; | ||
} | ||
return this; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); | ||
} | ||
getTransactionContext() { | ||
try { | ||
return this._transactionContextPropagator.getTransactionContext(); | ||
} catch (err) { | ||
const error = err; | ||
this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`); | ||
this._logger.error(error == null ? void 0 : error.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
// src/provider/no-op-provider.ts | ||
var import_core = require("@openfeature/core"); | ||
var REASON_NO_OP = "No-op"; | ||
@@ -656,3 +87,3 @@ var NoopFeatureProvider = class { | ||
get status() { | ||
return "NOT_READY" /* NOT_READY */; | ||
return import_core.ProviderStatus.NOT_READY; | ||
} | ||
@@ -680,4 +111,8 @@ resolveBooleanEvaluation(_, defaultValue) { | ||
// src/provider/in-memory-provider/in-memory-provider.ts | ||
var import_core3 = require("@openfeature/core"); | ||
// src/provider/in-memory-provider/variant-not-found-error.ts | ||
var VariantFoundError = class extends OpenFeatureError { | ||
var import_core2 = require("@openfeature/core"); | ||
var VariantFoundError = class extends import_core2.OpenFeatureError { | ||
constructor(message) { | ||
@@ -687,3 +122,3 @@ super(message); | ||
this.name = "VariantFoundError"; | ||
this.code = "GENERAL" /* GENERAL */; | ||
this.code = import_core2.ErrorCode.GENERAL; | ||
} | ||
@@ -695,3 +130,3 @@ }; | ||
constructor(flagConfiguration = {}) { | ||
this.events = new OpenFeatureEventEmitter(); | ||
this.events = new import_core3.OpenFeatureEventEmitter(); | ||
this.runsOn = "server"; | ||
@@ -710,3 +145,3 @@ this.metadata = { | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this.events.emit("PROVIDER_CONFIGURATION_CHANGED" /* ConfigurationChanged */, { flagsChanged }); | ||
this.events.emit(import_core3.ProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
} | ||
@@ -734,8 +169,8 @@ resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { | ||
if (typeof (resolutionResult == null ? void 0 : resolutionResult.value) != typeof defaultValue) { | ||
throw new TypeMismatchError(); | ||
throw new import_core3.TypeMismatchError(); | ||
} | ||
return resolutionResult; | ||
} catch (error) { | ||
if (!(error instanceof OpenFeatureError)) { | ||
throw new GeneralError((error == null ? void 0 : error.message) || "unknown error"); | ||
if (!(error instanceof import_core3.OpenFeatureError)) { | ||
throw new import_core3.GeneralError((error == null ? void 0 : error.message) || "unknown error"); | ||
} | ||
@@ -751,7 +186,7 @@ throw error; | ||
logger == null ? void 0 : logger.debug(message); | ||
throw new FlagNotFoundError(message); | ||
throw new import_core3.FlagNotFoundError(message); | ||
} | ||
const flagSpec = this._flagConfiguration[flagKey]; | ||
if (flagSpec.disabled) { | ||
return { value: defaultValue, reason: StandardResolutionReasons.DISABLED }; | ||
return { value: defaultValue, reason: import_core3.StandardResolutionReasons.DISABLED }; | ||
} | ||
@@ -769,3 +204,3 @@ const isContextEval = ctx && (flagSpec == null ? void 0 : flagSpec.contextEvaluator); | ||
}, variant && { variant }), { | ||
reason: isContextEval ? StandardResolutionReasons.TARGETING_MATCH : StandardResolutionReasons.STATIC | ||
reason: isContextEval ? import_core3.StandardResolutionReasons.TARGETING_MATCH : import_core3.StandardResolutionReasons.STATIC | ||
}); | ||
@@ -776,8 +211,22 @@ } | ||
// src/open-feature.ts | ||
var import_core4 = require("@openfeature/core"); | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback) { | ||
callback(); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class extends OpenFeatureCommonAPI { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
var OpenFeatureAPI = class extends import_core4.OpenFeatureCommonAPI { | ||
constructor() { | ||
super("server"); | ||
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
this._defaultProvider = NOOP_PROVIDER; | ||
@@ -808,5 +257,5 @@ } | ||
var _a, _b; | ||
const name = stringOrUndefined(nameOrContext); | ||
const version = stringOrUndefined(versionOrContext); | ||
const context = (_b = (_a = objectOrUndefined(nameOrContext)) != null ? _a : objectOrUndefined(versionOrContext)) != null ? _b : objectOrUndefined(contextOrUndefined); | ||
const name = (0, import_core4.stringOrUndefined)(nameOrContext); | ||
const version = (0, import_core4.stringOrUndefined)(versionOrContext); | ||
const context = (_b = (_a = (0, import_core4.objectOrUndefined)(nameOrContext)) != null ? _a : (0, import_core4.objectOrUndefined)(versionOrContext)) != null ? _b : (0, import_core4.objectOrUndefined)(contextOrUndefined); | ||
return new OpenFeatureClient( | ||
@@ -820,2 +269,33 @@ () => this.getProviderForClient(name), | ||
} | ||
/** | ||
* Clears all registered providers and resets the default provider. | ||
* @returns {Promise<void>} | ||
*/ | ||
clearProviders() { | ||
return super.clearProvidersAndSetDefault(NOOP_PROVIDER); | ||
} | ||
setTransactionContextPropagator(transactionContextPropagator) { | ||
const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); | ||
} else { | ||
this._transactionContextPropagator = transactionContextPropagator; | ||
} | ||
return this; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); | ||
} | ||
getTransactionContext() { | ||
try { | ||
return this._transactionContextPropagator.getTransactionContext(); | ||
} catch (err) { | ||
const error = err; | ||
this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`); | ||
this._logger.error(error == null ? void 0 : error.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
@@ -844,3 +324,3 @@ var OpenFeature = OpenFeatureAPI.getInstance(); | ||
this.emitterAccessor().addHandler(eventType, handler); | ||
const shouldRunNow = statusMatchesEvent(eventType, this._provider.status); | ||
const shouldRunNow = (0, import_core5.statusMatchesEvent)(eventType, this._provider.status); | ||
if (shouldRunNow) { | ||
@@ -861,3 +341,3 @@ try { | ||
setLogger(logger) { | ||
this._clientLogger = new SafeLogger(logger); | ||
this._clientLogger = new import_core5.SafeLogger(logger); | ||
return this; | ||
@@ -969,3 +449,3 @@ } | ||
const errorMessage = err == null ? void 0 : err.message; | ||
const errorCode = (err == null ? void 0 : err.code) || "GENERAL" /* GENERAL */; | ||
const errorCode = (err == null ? void 0 : err.code) || import_core5.ErrorCode.GENERAL; | ||
yield this.errorHooks(allHooksReversed, hookContext, err, options); | ||
@@ -976,3 +456,3 @@ return { | ||
value: defaultValue, | ||
reason: StandardResolutionReasons.ERROR, | ||
reason: import_core5.StandardResolutionReasons.ERROR, | ||
flagMetadata: Object.freeze({}), | ||
@@ -1043,12 +523,8 @@ flagKey | ||
}; | ||
// src/index.ts | ||
__reExport(src_exports, require("@openfeature/core"), module.exports); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
DefaultLogger, | ||
ErrorCode, | ||
FlagNotFoundError, | ||
GeneralError, | ||
InMemoryProvider, | ||
InternalEventEmitter, | ||
InvalidContextError, | ||
LOG_LEVELS, | ||
NOOP_PROVIDER, | ||
@@ -1058,19 +534,4 @@ NOOP_TRANSACTION_CONTEXT_PROPAGATOR, | ||
OpenFeatureAPI, | ||
OpenFeatureClient, | ||
OpenFeatureCommonAPI, | ||
OpenFeatureError, | ||
OpenFeatureEventEmitter, | ||
ParseError, | ||
ProviderEvents, | ||
ProviderStatus, | ||
SafeLogger, | ||
StandardResolutionReasons, | ||
TargetingKeyMissingError, | ||
TypeMismatchError, | ||
isObject, | ||
isString, | ||
objectOrUndefined, | ||
statusMatchesEvent, | ||
stringOrUndefined | ||
OpenFeatureClient | ||
}); | ||
//# sourceMappingURL=index.js.map |
@@ -41,545 +41,12 @@ var __defProp = Object.defineProperty; | ||
// ../shared/src/errors/open-feature-error-abstract.ts | ||
var OpenFeatureError = class extends Error { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, OpenFeatureError.prototype); | ||
this.name = "OpenFeatureError"; | ||
} | ||
}; | ||
// src/client/open-feature-client.ts | ||
import { | ||
ErrorCode as ErrorCode2, | ||
SafeLogger, | ||
StandardResolutionReasons as StandardResolutionReasons2, | ||
statusMatchesEvent | ||
} from "@openfeature/core"; | ||
// ../shared/src/evaluation/evaluation.ts | ||
var StandardResolutionReasons = { | ||
/** | ||
* The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. | ||
*/ | ||
TARGETING_MATCH: "TARGETING_MATCH", | ||
/** | ||
* The resolved value was the result of pseudorandom assignment. | ||
*/ | ||
SPLIT: "SPLIT", | ||
/** | ||
* The resolved value was the result of the flag being disabled in the management system. | ||
*/ | ||
DISABLED: "DISABLED", | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
DEFAULT: "DEFAULT", | ||
/** | ||
* The reason for the resolved value could not be determined. | ||
*/ | ||
UNKNOWN: "UNKNOWN", | ||
/** | ||
* The resolved value is static (no dynamic evaluation). | ||
*/ | ||
STATIC: "STATIC", | ||
/** | ||
* The resolved value was retrieved from cache. | ||
*/ | ||
CACHED: "CACHED", | ||
/** | ||
* The resolved value was the result of an error. | ||
* | ||
* Note: The `errorCode` and `errorMessage` fields may contain additional details of this error. | ||
*/ | ||
ERROR: "ERROR" | ||
}; | ||
var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => { | ||
ErrorCode2["PROVIDER_NOT_READY"] = "PROVIDER_NOT_READY"; | ||
ErrorCode2["FLAG_NOT_FOUND"] = "FLAG_NOT_FOUND"; | ||
ErrorCode2["PARSE_ERROR"] = "PARSE_ERROR"; | ||
ErrorCode2["TYPE_MISMATCH"] = "TYPE_MISMATCH"; | ||
ErrorCode2["TARGETING_KEY_MISSING"] = "TARGETING_KEY_MISSING"; | ||
ErrorCode2["INVALID_CONTEXT"] = "INVALID_CONTEXT"; | ||
ErrorCode2["GENERAL"] = "GENERAL"; | ||
return ErrorCode2; | ||
})(ErrorCode || {}); | ||
// ../shared/src/errors/general-error.ts | ||
var GeneralError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, GeneralError.prototype); | ||
this.name = "GeneralError"; | ||
this.code = "GENERAL" /* GENERAL */; | ||
} | ||
}; | ||
// ../shared/src/errors/flag-not-found-error.ts | ||
var FlagNotFoundError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, FlagNotFoundError.prototype); | ||
this.name = "FlagNotFoundError"; | ||
this.code = "FLAG_NOT_FOUND" /* FLAG_NOT_FOUND */; | ||
} | ||
}; | ||
// ../shared/src/errors/parse-error.ts | ||
var ParseError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, ParseError.prototype); | ||
this.name = "ParseError"; | ||
this.code = "PARSE_ERROR" /* PARSE_ERROR */; | ||
} | ||
}; | ||
// ../shared/src/errors/type-mismatch-error.ts | ||
var TypeMismatchError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, TypeMismatchError.prototype); | ||
this.name = "TypeMismatchError"; | ||
this.code = "TYPE_MISMATCH" /* TYPE_MISMATCH */; | ||
} | ||
}; | ||
// ../shared/src/errors/targeting-key-missing-error.ts | ||
var TargetingKeyMissingError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, TargetingKeyMissingError.prototype); | ||
this.name = "TargetingKeyMissingError"; | ||
this.code = "TARGETING_KEY_MISSING" /* TARGETING_KEY_MISSING */; | ||
} | ||
}; | ||
// ../shared/src/errors/invalid-context-error.ts | ||
var InvalidContextError = class extends OpenFeatureError { | ||
constructor(message) { | ||
super(message); | ||
Object.setPrototypeOf(this, InvalidContextError.prototype); | ||
this.name = "InvalidContextError"; | ||
this.code = "INVALID_CONTEXT" /* INVALID_CONTEXT */; | ||
} | ||
}; | ||
// ../shared/src/provider/provider.ts | ||
var ProviderStatus = /* @__PURE__ */ ((ProviderStatus2) => { | ||
ProviderStatus2["NOT_READY"] = "NOT_READY"; | ||
ProviderStatus2["READY"] = "READY"; | ||
ProviderStatus2["ERROR"] = "ERROR"; | ||
ProviderStatus2["STALE"] = "STALE"; | ||
return ProviderStatus2; | ||
})(ProviderStatus || {}); | ||
// ../shared/src/events/events.ts | ||
var ProviderEvents = /* @__PURE__ */ ((ProviderEvents3) => { | ||
ProviderEvents3["Ready"] = "PROVIDER_READY"; | ||
ProviderEvents3["Error"] = "PROVIDER_ERROR"; | ||
ProviderEvents3["ConfigurationChanged"] = "PROVIDER_CONFIGURATION_CHANGED"; | ||
ProviderEvents3["Stale"] = "PROVIDER_STALE"; | ||
return ProviderEvents3; | ||
})(ProviderEvents || {}); | ||
// ../shared/src/events/event-utils.ts | ||
var eventStatusMap = { | ||
["READY" /* READY */]: "PROVIDER_READY" /* Ready */, | ||
["ERROR" /* ERROR */]: "PROVIDER_ERROR" /* Error */, | ||
["STALE" /* STALE */]: "PROVIDER_STALE" /* Stale */, | ||
["NOT_READY" /* NOT_READY */]: void 0 | ||
}; | ||
var statusMatchesEvent = (event, status) => { | ||
return !status && event === "PROVIDER_READY" /* Ready */ || eventStatusMap[status] === event; | ||
}; | ||
// ../shared/src/events/open-feature-event-emitter.ts | ||
import EventEmitter from "events"; | ||
// ../shared/src/logger/default-logger.ts | ||
var DefaultLogger = class { | ||
error(...args) { | ||
console.error(...args); | ||
} | ||
warn(...args) { | ||
console.warn(...args); | ||
} | ||
info() { | ||
} | ||
debug() { | ||
} | ||
}; | ||
// ../shared/src/logger/safe-logger.ts | ||
var LOG_LEVELS = ["error", "warn", "info", "debug"]; | ||
var SafeLogger = class { | ||
constructor(logger) { | ||
this.fallbackLogger = new DefaultLogger(); | ||
try { | ||
for (const level of LOG_LEVELS) { | ||
if (!logger[level] || typeof logger[level] !== "function") { | ||
throw new Error(`The provided logger is missing the ${level} method.`); | ||
} | ||
} | ||
this.logger = logger; | ||
} catch (err) { | ||
console.error(err); | ||
console.error("Falling back to the default logger."); | ||
this.logger = this.fallbackLogger; | ||
} | ||
} | ||
error(...args) { | ||
this.log("error", ...args); | ||
} | ||
warn(...args) { | ||
this.log("warn", ...args); | ||
} | ||
info(...args) { | ||
this.log("info", ...args); | ||
} | ||
debug(...args) { | ||
this.log("debug", ...args); | ||
} | ||
log(level, ...args) { | ||
try { | ||
this.logger[level](...args); | ||
} catch (error) { | ||
this.fallbackLogger[level](...args); | ||
} | ||
} | ||
}; | ||
// ../shared/src/events/open-feature-event-emitter.ts | ||
var GenericEventEmitter = class { | ||
constructor(globalLogger) { | ||
this.globalLogger = globalLogger; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
this._handlers = /* @__PURE__ */ new WeakMap(); | ||
this.eventEmitter = new EventEmitter({ 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 = (details) => __async(this, null, function* () { | ||
yield handler(details); | ||
}); | ||
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, _b; | ||
return (_b = this._eventLogger) != null ? _b : (_a = this.globalLogger) == null ? void 0 : _a.call(this); | ||
} | ||
}; | ||
var OpenFeatureEventEmitter = class extends GenericEventEmitter { | ||
}; | ||
var InternalEventEmitter = class extends GenericEventEmitter { | ||
}; | ||
// ../shared/src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback) { | ||
callback(); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// ../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/filter.ts | ||
function isDefined(input) { | ||
return typeof input !== "undefined" && input !== null; | ||
} | ||
// ../shared/src/open-feature.ts | ||
var OpenFeatureCommonAPI = class { | ||
constructor(category) { | ||
this._hooks = []; | ||
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
this._context = {}; | ||
this._logger = new DefaultLogger(); | ||
this._events = new InternalEventEmitter(() => this._logger); | ||
this._clientEventHandlers = /* @__PURE__ */ new Map(); | ||
this._clientProviders = /* @__PURE__ */ new Map(); | ||
this._clientEvents = /* @__PURE__ */ new Map(); | ||
this._runsOn = category; | ||
} | ||
addHooks(...hooks) { | ||
this._hooks = [...this._hooks, ...hooks]; | ||
return this; | ||
} | ||
getHooks() { | ||
return this._hooks; | ||
} | ||
clearHooks() { | ||
this._hooks = []; | ||
return this; | ||
} | ||
setLogger(logger) { | ||
this._logger = new SafeLogger(logger); | ||
return this; | ||
} | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata() { | ||
return this._defaultProvider.metadata; | ||
} | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* API (global) events run for all providers. | ||
* @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) { | ||
[.../* @__PURE__ */ new Map([[void 0, this._defaultProvider]]), ...this._clientProviders].forEach((keyProviderTuple) => { | ||
var _a; | ||
const clientName = keyProviderTuple[0]; | ||
const provider = keyProviderTuple[1]; | ||
const shouldRunNow = statusMatchesEvent(eventType, keyProviderTuple[1].status); | ||
if (shouldRunNow) { | ||
try { | ||
handler({ clientName, providerName: provider.metadata.name }); | ||
} catch (err) { | ||
(_a = this._logger) == null ? void 0 : _a.error("Error running event handler:", err); | ||
} | ||
} | ||
}); | ||
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); | ||
} | ||
setProviderAndWait(clientOrProvider, providerOrUndefined) { | ||
return __async(this, null, function* () { | ||
yield this.setAwaitableProvider(clientOrProvider, providerOrUndefined); | ||
}); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
const maybePromise = this.setAwaitableProvider(clientOrProvider, providerOrUndefined); | ||
if (maybePromise) { | ||
maybePromise.catch(() => { | ||
}); | ||
} | ||
return this; | ||
} | ||
setAwaitableProvider(clientOrProvider, providerOrUndefined) { | ||
var _a, _b, _c, _d, _e, _f; | ||
const clientName = stringOrUndefined(clientOrProvider); | ||
const provider = (_a = objectOrUndefined(clientOrProvider)) != null ? _a : objectOrUndefined(providerOrUndefined); | ||
if (!provider) { | ||
this._logger.debug("No provider defined, ignoring setProvider call"); | ||
return; | ||
} | ||
const oldProvider = this.getProviderForClient(clientName); | ||
const providerName = provider.metadata.name; | ||
if (oldProvider === provider) { | ||
this._logger.debug("Provider is already set, ignoring setProvider call"); | ||
return; | ||
} | ||
if (!provider.runsOn) { | ||
this._logger.debug(`Provider '${provider.metadata.name}' has not defined its intended use.`); | ||
} else if (provider.runsOn !== this._runsOn) { | ||
throw new GeneralError(`Provider '${provider.metadata.name}' is intended for use on the ${provider.runsOn}.`); | ||
} | ||
const emitters = this.getAssociatedEventEmitters(clientName); | ||
if (typeof provider.initialize === "function" && provider.status === void 0) { | ||
const activeLogger = this._logger || console; | ||
activeLogger.warn( | ||
`Provider ${providerName} implements 'initialize' but not 'status'. Please implement 'status'.` | ||
); | ||
} | ||
let initializationPromise = void 0; | ||
if ((provider == null ? void 0 : provider.status) === "NOT_READY" /* NOT_READY */ && typeof provider.initialize === "function") { | ||
initializationPromise = (_d = (_c = (_b = provider.initialize) == null ? void 0 : _b.call(provider, this._context)) == null ? void 0 : _c.then(() => { | ||
var _a2; | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
}); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
})) == null ? void 0 : _d.catch((error) => { | ||
var _a2; | ||
this.getAssociatedEventEmitters(clientName).forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message }); | ||
}); | ||
(_a2 = this._events) == null ? void 0 : _a2.emit("PROVIDER_ERROR" /* Error */, { clientName, providerName, message: error.message }); | ||
throw error; | ||
}); | ||
} else { | ||
emitters.forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
}); | ||
(_e = this._events) == null ? void 0 : _e.emit("PROVIDER_READY" /* Ready */, { clientName, providerName }); | ||
} | ||
if (clientName) { | ||
this._clientProviders.set(clientName, provider); | ||
} else { | ||
this._defaultProvider = provider; | ||
} | ||
this.transferListeners(oldProvider, provider, clientName, emitters); | ||
if (![...this._clientProviders.values(), this._defaultProvider].includes(oldProvider)) { | ||
(_f = oldProvider == null ? void 0 : oldProvider.onClose) == null ? void 0 : _f.call(oldProvider); | ||
} | ||
return initializationPromise; | ||
} | ||
getProviderForClient(name) { | ||
var _a; | ||
if (!name) { | ||
return this._defaultProvider; | ||
} | ||
return (_a = this._clientProviders.get(name)) != null ? _a : this._defaultProvider; | ||
} | ||
buildAndCacheEventEmitterForClient(name) { | ||
const emitter = this._clientEvents.get(name); | ||
if (emitter) { | ||
return emitter; | ||
} | ||
const newEmitter = new InternalEventEmitter(() => this._logger); | ||
this._clientEvents.set(name, newEmitter); | ||
const clientProvider = this.getProviderForClient(name); | ||
Object.values(ProviderEvents).forEach( | ||
(eventType) => { | ||
var _a; | ||
return (_a = clientProvider.events) == null ? void 0 : _a.addHandler(eventType, (details) => __async(this, null, function* () { | ||
newEmitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName: name, providerName: clientProvider.metadata.name })); | ||
})); | ||
} | ||
); | ||
return newEmitter; | ||
} | ||
getUnboundEmitters() { | ||
const namedProviders = [...this._clientProviders.keys()]; | ||
const eventEmitterNames = [...this._clientEvents.keys()].filter(isDefined); | ||
const unboundEmitterNames = eventEmitterNames.filter((name) => !namedProviders.includes(name)); | ||
return [ | ||
// all unbound, named emitters | ||
...unboundEmitterNames.map((name) => this._clientEvents.get(name)), | ||
// the default emitter | ||
this._clientEvents.get(void 0) | ||
].filter(isDefined); | ||
} | ||
getAssociatedEventEmitters(clientName) { | ||
return clientName ? [this.buildAndCacheEventEmitterForClient(clientName)] : this.getUnboundEmitters(); | ||
} | ||
transferListeners(oldProvider, newProvider, clientName, emitters) { | ||
var _a; | ||
(_a = this._clientEventHandlers.get(clientName)) == null ? void 0 : _a.forEach((eventHandler) => { | ||
var _a2; | ||
return (_a2 = oldProvider.events) == null ? void 0 : _a2.removeHandler(...eventHandler); | ||
}); | ||
const newClientHandlers = Object.values(ProviderEvents).map((eventType) => { | ||
const handler = (details) => __async(this, null, function* () { | ||
emitters.forEach((emitter) => { | ||
emitter == null ? void 0 : emitter.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name })); | ||
}); | ||
this._events.emit(eventType, __spreadProps(__spreadValues({}, details), { clientName, providerName: newProvider.metadata.name })); | ||
}); | ||
return [eventType, handler]; | ||
}); | ||
this._clientEventHandlers.set(clientName, newClientHandlers); | ||
newClientHandlers.forEach((eventHandler) => { | ||
var _a2; | ||
return (_a2 = newProvider.events) == null ? void 0 : _a2.addHandler(...eventHandler); | ||
}); | ||
} | ||
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) { | ||
const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); | ||
} else { | ||
this._transactionContextPropagator = transactionContextPropagator; | ||
} | ||
return this; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); | ||
} | ||
getTransactionContext() { | ||
try { | ||
return this._transactionContextPropagator.getTransactionContext(); | ||
} catch (err) { | ||
const error = err; | ||
this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`); | ||
this._logger.error(error == null ? void 0 : error.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
// src/provider/no-op-provider.ts | ||
import { ProviderStatus } from "@openfeature/core"; | ||
var REASON_NO_OP = "No-op"; | ||
@@ -593,3 +60,3 @@ var NoopFeatureProvider = class { | ||
get status() { | ||
return "NOT_READY" /* NOT_READY */; | ||
return ProviderStatus.NOT_READY; | ||
} | ||
@@ -617,3 +84,15 @@ resolveBooleanEvaluation(_, defaultValue) { | ||
// src/provider/in-memory-provider/in-memory-provider.ts | ||
import { | ||
FlagNotFoundError, | ||
GeneralError, | ||
OpenFeatureError as OpenFeatureError2, | ||
OpenFeatureEventEmitter, | ||
ProviderEvents, | ||
StandardResolutionReasons, | ||
TypeMismatchError | ||
} from "@openfeature/core"; | ||
// src/provider/in-memory-provider/variant-not-found-error.ts | ||
import { ErrorCode, OpenFeatureError } from "@openfeature/core"; | ||
var VariantFoundError = class extends OpenFeatureError { | ||
@@ -624,3 +103,3 @@ constructor(message) { | ||
this.name = "VariantFoundError"; | ||
this.code = "GENERAL" /* GENERAL */; | ||
this.code = ErrorCode.GENERAL; | ||
} | ||
@@ -646,3 +125,3 @@ }; | ||
this._flagConfiguration = __spreadValues({}, flagConfiguration); | ||
this.events.emit("PROVIDER_CONFIGURATION_CHANGED" /* ConfigurationChanged */, { flagsChanged }); | ||
this.events.emit(ProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
} | ||
@@ -674,3 +153,3 @@ resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { | ||
} catch (error) { | ||
if (!(error instanceof OpenFeatureError)) { | ||
if (!(error instanceof OpenFeatureError2)) { | ||
throw new GeneralError((error == null ? void 0 : error.message) || "unknown error"); | ||
@@ -710,8 +189,26 @@ } | ||
// src/open-feature.ts | ||
import { | ||
OpenFeatureCommonAPI, | ||
objectOrUndefined, | ||
stringOrUndefined | ||
} from "@openfeature/core"; | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback) { | ||
callback(); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class extends OpenFeatureCommonAPI { | ||
// eslint-disable-next-line @typescript-eslint/no-empty-function | ||
constructor() { | ||
super("server"); | ||
this._transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
this._defaultProvider = NOOP_PROVIDER; | ||
@@ -753,2 +250,33 @@ } | ||
} | ||
/** | ||
* Clears all registered providers and resets the default provider. | ||
* @returns {Promise<void>} | ||
*/ | ||
clearProviders() { | ||
return super.clearProvidersAndSetDefault(NOOP_PROVIDER); | ||
} | ||
setTransactionContextPropagator(transactionContextPropagator) { | ||
const baseMessage = "Invalid TransactionContextPropagator, will not be set: "; | ||
if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.getTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof (transactionContextPropagator == null ? void 0 : transactionContextPropagator.setTransactionContext) !== "function") { | ||
this._logger.error(`${baseMessage}: setTransactionContext is not a function.`); | ||
} else { | ||
this._transactionContextPropagator = transactionContextPropagator; | ||
} | ||
return this; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this._transactionContextPropagator.setTransactionContext(transactionContext, callback, ...args); | ||
} | ||
getTransactionContext() { | ||
try { | ||
return this._transactionContextPropagator.getTransactionContext(); | ||
} catch (err) { | ||
const error = err; | ||
this._logger.error(`Error getting transaction context: ${error == null ? void 0 : error.message}, returning empty context.`); | ||
this._logger.error(error == null ? void 0 : error.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
@@ -900,3 +428,3 @@ var OpenFeature = OpenFeatureAPI.getInstance(); | ||
const errorMessage = err == null ? void 0 : err.message; | ||
const errorCode = (err == null ? void 0 : err.code) || "GENERAL" /* GENERAL */; | ||
const errorCode = (err == null ? void 0 : err.code) || ErrorCode2.GENERAL; | ||
yield this.errorHooks(allHooksReversed, hookContext, err, options); | ||
@@ -907,3 +435,3 @@ return { | ||
value: defaultValue, | ||
reason: StandardResolutionReasons.ERROR, | ||
reason: StandardResolutionReasons2.ERROR, | ||
flagMetadata: Object.freeze({}), | ||
@@ -974,11 +502,7 @@ flagKey | ||
}; | ||
// src/index.ts | ||
export * from "@openfeature/core"; | ||
export { | ||
DefaultLogger, | ||
ErrorCode, | ||
FlagNotFoundError, | ||
GeneralError, | ||
InMemoryProvider, | ||
InternalEventEmitter, | ||
InvalidContextError, | ||
LOG_LEVELS, | ||
NOOP_PROVIDER, | ||
@@ -988,19 +512,4 @@ NOOP_TRANSACTION_CONTEXT_PROPAGATOR, | ||
OpenFeatureAPI, | ||
OpenFeatureClient, | ||
OpenFeatureCommonAPI, | ||
OpenFeatureError, | ||
OpenFeatureEventEmitter, | ||
ParseError, | ||
ProviderEvents, | ||
ProviderStatus, | ||
SafeLogger, | ||
StandardResolutionReasons, | ||
TargetingKeyMissingError, | ||
TypeMismatchError, | ||
isObject, | ||
isString, | ||
objectOrUndefined, | ||
statusMatchesEvent, | ||
stringOrUndefined | ||
OpenFeatureClient | ||
}; | ||
//# sourceMappingURL=index.js.map |
@@ -1,629 +0,4 @@ | ||
type FlagValueType = 'boolean' | 'string' | 'number' | 'object'; | ||
type PrimitiveValue = null | boolean | string | number; | ||
type JsonObject = { | ||
[key: string]: JsonValue; | ||
}; | ||
type JsonArray = JsonValue[]; | ||
/** | ||
* Represents a JSON node value. | ||
*/ | ||
type JsonValue = PrimitiveValue | JsonObject | JsonArray; | ||
/** | ||
* Represents a JSON node value, or Date. | ||
*/ | ||
type FlagValue = boolean | string | number | JsonValue; | ||
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; | ||
errorCode?: ErrorCode; | ||
errorMessage?: string; | ||
}; | ||
type EvaluationDetails<T extends FlagValue> = { | ||
flagKey: string; | ||
flagMetadata: Readonly<FlagMetadata>; | ||
} & ResolutionDetails<T>; | ||
declare const StandardResolutionReasons: { | ||
/** | ||
* The resolved value was the result of a dynamic evaluation, such as a rule or specific user-targeting. | ||
*/ | ||
readonly TARGETING_MATCH: "TARGETING_MATCH"; | ||
/** | ||
* The resolved value was the result of pseudorandom assignment. | ||
*/ | ||
readonly SPLIT: "SPLIT"; | ||
/** | ||
* The resolved value was the result of the flag being disabled in the management system. | ||
*/ | ||
readonly DISABLED: "DISABLED"; | ||
/** | ||
* The resolved value was configured statically, or otherwise fell back to a pre-configured value. | ||
*/ | ||
readonly DEFAULT: "DEFAULT"; | ||
/** | ||
* The reason for the resolved value could not be determined. | ||
*/ | ||
readonly UNKNOWN: "UNKNOWN"; | ||
/** | ||
* The resolved value is static (no dynamic evaluation). | ||
*/ | ||
readonly STATIC: "STATIC"; | ||
/** | ||
* The resolved value was retrieved from cache. | ||
*/ | ||
readonly CACHED: "CACHED"; | ||
/** | ||
* The resolved value was the result of an error. | ||
* | ||
* Note: The `errorCode` and `errorMessage` fields may contain additional details of this error. | ||
*/ | ||
readonly ERROR: "ERROR"; | ||
}; | ||
declare enum ErrorCode { | ||
/** | ||
* The value was resolved before the provider was ready. | ||
*/ | ||
PROVIDER_NOT_READY = "PROVIDER_NOT_READY", | ||
/** | ||
* The flag could not be found. | ||
*/ | ||
FLAG_NOT_FOUND = "FLAG_NOT_FOUND", | ||
/** | ||
* An error was encountered parsing data, such as a flag configuration. | ||
*/ | ||
PARSE_ERROR = "PARSE_ERROR", | ||
/** | ||
* The type of the flag value does not match the expected type. | ||
*/ | ||
TYPE_MISMATCH = "TYPE_MISMATCH", | ||
/** | ||
* The provider requires a targeting key and one was not provided in the evaluation context. | ||
*/ | ||
TARGETING_KEY_MISSING = "TARGETING_KEY_MISSING", | ||
/** | ||
* The evaluation context does not meet provider requirements. | ||
*/ | ||
INVALID_CONTEXT = "INVALID_CONTEXT", | ||
/** | ||
* An error with an unspecified code. | ||
*/ | ||
GENERAL = "GENERAL" | ||
} | ||
import { Hook, HookHints, EvaluationContext, EvaluationDetails, JsonValue, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, CommonProvider, Logger, ResolutionDetails, ProviderStatus, OpenFeatureEventEmitter, InternalEventEmitter, ProviderEvents, EventHandler, FlagValue, OpenFeatureCommonAPI } from '@openfeature/core'; | ||
export * from '@openfeature/core'; | ||
type EvaluationContextValue = PrimitiveValue | Date | { | ||
[key: string]: EvaluationContextValue; | ||
} | EvaluationContextValue[]; | ||
/** | ||
* A container for arbitrary contextual data that can be used as a basis for dynamic evaluation | ||
*/ | ||
type EvaluationContext = { | ||
/** | ||
* A string uniquely identifying the subject (end-user, or client service) of a flag evaluation. | ||
* Providers may require this field for fractional flag evaluation, rules, or overrides targeting specific users. | ||
* Such providers may behave unpredictably if a targeting key is not specified at flag resolution. | ||
*/ | ||
targetingKey?: string; | ||
} & Record<string, EvaluationContextValue>; | ||
interface ManageContext<T> { | ||
/** | ||
* Access the evaluation context set on the receiver. | ||
* @returns {EvaluationContext} Evaluation context | ||
*/ | ||
getContext(): EvaluationContext; | ||
/** | ||
* Sets evaluation context that will be used during flag evaluations | ||
* on this receiver. | ||
* @template T The type of the receiver | ||
* @param {EvaluationContext} context Evaluation context | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
setContext(context: EvaluationContext): T; | ||
} | ||
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" | ||
} | ||
/** | ||
* Returns true if the provider's status corresponds to the event. | ||
* If the provider's status is not defined, it matches READY. | ||
* @param {ProviderEvents} event event to match | ||
* @param {ProviderStatus} status status of provider | ||
* @returns {boolean} boolean indicating if the provider status corresponds to the event. | ||
*/ | ||
declare const statusMatchesEvent: (event: ProviderEvents, status?: ProviderStatus) => boolean; | ||
type EventMetadata = { | ||
[key: string]: string | boolean | number; | ||
}; | ||
type CommonEventDetails = { | ||
providerName: string; | ||
clientName?: string; | ||
}; | ||
type CommonEventProps = { | ||
message?: string; | ||
metadata?: EventMetadata; | ||
}; | ||
type ReadyEvent = CommonEventProps; | ||
type ErrorEvent = CommonEventProps; | ||
type StaleEvent = CommonEventProps; | ||
type ConfigChangeEvent = CommonEventProps & { | ||
flagsChanged?: string[]; | ||
}; | ||
type EventMap = { | ||
[ProviderEvents.Ready]: ReadyEvent; | ||
[ProviderEvents.Error]: ErrorEvent; | ||
[ProviderEvents.Stale]: StaleEvent; | ||
[ProviderEvents.ConfigurationChanged]: ConfigChangeEvent; | ||
}; | ||
type EventContext<T extends ProviderEvents, U extends Record<string, unknown> = Record<string, unknown>> = EventMap[T] & U; | ||
type EventDetails<T extends ProviderEvents> = EventContext<T> & CommonEventDetails; | ||
type EventHandler<T extends ProviderEvents> = (eventDetails?: EventDetails<T>) => 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<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): 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<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): 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<T extends ProviderEvents>(eventType: T): EventHandler<T>[]; | ||
} | ||
interface Logger { | ||
error(...args: unknown[]): void; | ||
warn(...args: unknown[]): void; | ||
info(...args: unknown[]): void; | ||
debug(...args: unknown[]): void; | ||
} | ||
interface ManageLogger<T> { | ||
/** | ||
* Sets a logger on this receiver. This logger supersedes to the global logger | ||
* and is passed to various components in the SDK. | ||
* The logger configured on the global API object will be used for all evaluations, | ||
* unless overridden in a particular client. | ||
* @template T The type of the receiver | ||
* @param {Logger} logger The logger to be used | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
setLogger(logger: Logger): T; | ||
} | ||
declare class DefaultLogger implements Logger { | ||
error(...args: unknown[]): void; | ||
warn(...args: unknown[]): void; | ||
info(): void; | ||
debug(): void; | ||
} | ||
declare const LOG_LEVELS: Array<keyof Logger>; | ||
declare class SafeLogger implements Logger { | ||
private readonly logger; | ||
private readonly fallbackLogger; | ||
constructor(logger: Logger); | ||
error(...args: unknown[]): void; | ||
warn(...args: unknown[]): void; | ||
info(...args: unknown[]): void; | ||
debug(...args: unknown[]): void; | ||
private log; | ||
} | ||
declare abstract class GenericEventEmitter<AdditionalContext extends Record<string, unknown> = Record<string, unknown>> implements ManageLogger<GenericEventEmitter<AdditionalContext>> { | ||
private readonly globalLogger?; | ||
private readonly _handlers; | ||
private readonly eventEmitter; | ||
private _eventLogger?; | ||
constructor(globalLogger?: (() => Logger) | undefined); | ||
emit<T extends ProviderEvents>(eventType: T, context?: EventContext<T, AdditionalContext>): void; | ||
addHandler<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): void; | ||
removeHandler<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): void; | ||
removeAllHandlers(eventType?: ProviderEvents): void; | ||
getHandlers<T extends ProviderEvents>(eventType: T): EventHandler<T>[]; | ||
setLogger(logger: Logger): this; | ||
private get _logger(); | ||
} | ||
/** | ||
* The OpenFeatureEventEmitter can be used by provider developers to emit | ||
* events at various parts of the provider lifecycle. | ||
* | ||
* NOTE: Ready and error events are automatically emitted by the SDK based on | ||
* the result of the initialize method. | ||
*/ | ||
declare class OpenFeatureEventEmitter extends GenericEventEmitter { | ||
} | ||
/** | ||
* The InternalEventEmitter should only be used within the SDK. It extends the | ||
* OpenFeatureEventEmitter to include additional properties that can be included | ||
* in the event details. | ||
*/ | ||
declare class InternalEventEmitter extends GenericEventEmitter<CommonEventDetails> { | ||
} | ||
interface Metadata { | ||
} | ||
/** | ||
* Defines where the library is intended to be run. | ||
*/ | ||
type Paradigm = 'server' | 'client'; | ||
/** | ||
* The state of the provider. | ||
*/ | ||
declare enum ProviderStatus { | ||
/** | ||
* The provider has not been initialized and cannot yet evaluate flags. | ||
*/ | ||
NOT_READY = "NOT_READY", | ||
/** | ||
* The provider is ready to resolve flags. | ||
*/ | ||
READY = "READY", | ||
/** | ||
* The provider is in an error state and unable to evaluate flags. | ||
*/ | ||
ERROR = "ERROR", | ||
/** | ||
* The provider's cached state is no longer valid and may not be up-to-date with the source of truth. | ||
*/ | ||
STALE = "STALE" | ||
} | ||
/** | ||
* Static data about the provider. | ||
*/ | ||
interface ProviderMetadata extends Metadata { | ||
readonly name: string; | ||
} | ||
interface CommonProvider { | ||
readonly metadata: ProviderMetadata; | ||
/** | ||
* Represents where the provider is intended to be run. If defined, | ||
* the SDK will enforce that the defined paradigm at runtime. | ||
*/ | ||
readonly runsOn?: Paradigm; | ||
/** | ||
* Returns a representation of the current readiness of the provider. | ||
* If the provider needs to be initialized, it should return {@link ProviderStatus.READY}. | ||
* If the provider is in an error state, it should return {@link ProviderStatus.ERROR}. | ||
* If the provider is functioning normally, it should return {@link ProviderStatus.NOT_READY}. | ||
* | ||
* _Providers which do not implement this method are assumed to be ready immediately._ | ||
*/ | ||
readonly status?: ProviderStatus; | ||
/** | ||
* An event emitter for ProviderEvents. | ||
* @see ProviderEvents | ||
*/ | ||
events?: OpenFeatureEventEmitter; | ||
/** | ||
* A function used to shut down the provider. | ||
* Called when this provider is replaced with a new one, or when the OpenFeature is shut down. | ||
*/ | ||
onClose?(): Promise<void>; | ||
/** | ||
* A function used to setup the provider. | ||
* Called by the SDK after the provider is set if the provider's status is {@link ProviderStatus.NOT_READY}. | ||
* 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>; | ||
} | ||
interface ClientMetadata extends Metadata { | ||
readonly version?: string; | ||
readonly name?: string; | ||
readonly providerMetadata: ProviderMetadata; | ||
} | ||
type HookHints = Readonly<Record<string, unknown>>; | ||
interface HookContext<T extends FlagValue = FlagValue> { | ||
readonly flagKey: string; | ||
readonly defaultValue: T; | ||
readonly flagValueType: FlagValueType; | ||
readonly context: Readonly<EvaluationContext>; | ||
readonly clientMetadata: ClientMetadata; | ||
readonly providerMetadata: ProviderMetadata; | ||
readonly logger: Logger; | ||
} | ||
interface BeforeHookContext extends HookContext { | ||
context: EvaluationContext; | ||
} | ||
interface Hook<T extends FlagValue = FlagValue> { | ||
/** | ||
* Runs before flag values are resolved from the provider. | ||
* If an EvaluationContext is returned, it will be merged with the pre-existing EvaluationContext. | ||
* @param hookContext | ||
* @param hookHints | ||
*/ | ||
before?(hookContext: BeforeHookContext, hookHints?: HookHints): Promise<EvaluationContext | void> | EvaluationContext | void; | ||
/** | ||
* Runs after flag values are successfully resolved from the provider. | ||
* @param hookContext | ||
* @param evaluationDetails | ||
* @param hookHints | ||
*/ | ||
after?(hookContext: Readonly<HookContext<T>>, evaluationDetails: EvaluationDetails<T>, hookHints?: HookHints): Promise<void> | void; | ||
/** | ||
* Runs in the event of an unhandled error or promise rejection during flag resolution, or any attached hooks. | ||
* @param hookContext | ||
* @param error | ||
* @param hookHints | ||
*/ | ||
error?(hookContext: Readonly<HookContext<T>>, error: unknown, hookHints?: HookHints): Promise<void> | void; | ||
/** | ||
* Runs after all other hook stages, regardless of success or error. | ||
* Errors thrown here are unhandled by the client and will surface in application code. | ||
* @param hookContext | ||
* @param hookHints | ||
*/ | ||
finally?(hookContext: Readonly<HookContext<T>>, hookHints?: HookHints): Promise<void> | void; | ||
} | ||
interface EvaluationLifeCycle<T> { | ||
/** | ||
* Adds hooks that will run during flag evaluations on this receiver. | ||
* Hooks are executed in the order they were registered. Adding additional hooks | ||
* will not remove existing hooks. | ||
* Hooks registered on the global API object run with all evaluations. | ||
* Hooks registered on the client run with all evaluations on that client. | ||
* @template T The type of the receiver | ||
* @param {Hook<FlagValue>[]} hooks A list of hooks that should always run | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
addHooks(...hooks: Hook<FlagValue>[]): T; | ||
/** | ||
* Access all the hooks that are registered on this receiver. | ||
* @returns {Hook<FlagValue>[]} A list of the client hooks | ||
*/ | ||
getHooks(): Hook<FlagValue>[]; | ||
/** | ||
* Clears all the hooks that are registered on this receiver. | ||
* @template T The type of the receiver | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
clearHooks(): T; | ||
} | ||
declare abstract class OpenFeatureError extends Error { | ||
abstract code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class GeneralError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class FlagNotFoundError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class ParseError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class TypeMismatchError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class TargetingKeyMissingError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
declare class InvalidContextError extends OpenFeatureError { | ||
code: ErrorCode; | ||
constructor(message?: string); | ||
} | ||
/** | ||
* Transaction context is a mechanism for adding transaction specific context that | ||
* is merged with evaluation context prior to flag evaluation. Examples of potential | ||
* transaction specific context include: a user id, user agent, or request path. | ||
*/ | ||
type TransactionContext = EvaluationContext; | ||
interface ManageTransactionContextPropagator<T> extends TransactionContextPropagator { | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Sets a transaction context propagator on this receiver. The transaction context | ||
* propagator is responsible for persisting context for the duration of a single | ||
* transaction. | ||
* @experimental | ||
* @template T The type of the receiver | ||
* @param {TransactionContextPropagator} transactionContextPropagator The context propagator to be used | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
setTransactionContextPropagator(transactionContextPropagator: TransactionContextPropagator): T; | ||
} | ||
interface TransactionContextPropagator { | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Returns the currently defined transaction context using the registered transaction | ||
* context propagator. | ||
* @experimental | ||
* @returns {TransactionContext} The current transaction context | ||
*/ | ||
getTransactionContext(): TransactionContext; | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Sets the transaction context using the registered transaction context propagator. | ||
* @experimental | ||
* @template R The return value of the callback | ||
* @param {TransactionContext} transactionContext The transaction specific context | ||
* @param {(...args: unknown[]) => R} callback Callback function used to set the transaction context on the stack | ||
* @param {...unknown[]} args Optional arguments that are passed to the callback function | ||
*/ | ||
setTransactionContext<R>(transactionContext: TransactionContext, callback: (...args: unknown[]) => R, ...args: unknown[]): void; | ||
} | ||
declare class NoopTransactionContextPropagator implements TransactionContextPropagator { | ||
getTransactionContext(): EvaluationContext; | ||
setTransactionContext(_: EvaluationContext, callback: () => void): void; | ||
} | ||
declare const NOOP_TRANSACTION_CONTEXT_PROPAGATOR: NoopTransactionContextPropagator; | ||
/** | ||
* Checks whether the parameter is a string. | ||
* @param {unknown} value The value to check | ||
* @returns {value is string} True if the value is a string | ||
*/ | ||
declare function isString(value: unknown): value is string; | ||
/** | ||
* Returns the parameter if it is a string, otherwise returns undefined. | ||
* @param {unknown} value The value to check | ||
* @returns {string|undefined} The parameter if it is a string, otherwise undefined | ||
*/ | ||
declare function stringOrUndefined(value: unknown): string | undefined; | ||
/** | ||
* Checks whether the parameter is an object. | ||
* @param {unknown} value The value to check | ||
* @returns {value is string} True if the value is an object | ||
*/ | ||
declare function isObject<T extends object>(value: unknown): value is T; | ||
/** | ||
* Returns the parameter if it is an object, otherwise returns undefined. | ||
* @param {unknown} value The value to check | ||
* @returns {object|undefined} The parameter if it is an object, otherwise undefined | ||
*/ | ||
declare function objectOrUndefined<T extends object>(value: unknown): T | undefined; | ||
declare abstract class OpenFeatureCommonAPI<P extends CommonProvider = CommonProvider> implements Eventing, EvaluationLifeCycle<OpenFeatureCommonAPI<P>>, ManageLogger<OpenFeatureCommonAPI<P>>, ManageTransactionContextPropagator<OpenFeatureCommonAPI<P>> { | ||
protected _hooks: Hook[]; | ||
protected _transactionContextPropagator: TransactionContextPropagator; | ||
protected _context: EvaluationContext; | ||
protected _logger: Logger; | ||
protected abstract _defaultProvider: P; | ||
private readonly _events; | ||
private readonly _clientEventHandlers; | ||
protected _clientProviders: Map<string, P>; | ||
protected _clientEvents: Map<string | undefined, InternalEventEmitter>; | ||
protected _runsOn: Paradigm; | ||
constructor(category: Paradigm); | ||
addHooks(...hooks: Hook<FlagValue>[]): this; | ||
getHooks(): Hook<FlagValue>[]; | ||
clearHooks(): this; | ||
setLogger(logger: Logger): this; | ||
/** | ||
* Get metadata about registered provider. | ||
* @returns {ProviderMetadata} Provider Metadata | ||
*/ | ||
get providerMetadata(): ProviderMetadata; | ||
/** | ||
* Adds a handler for the given provider event type. | ||
* The handlers are called in the order they have been added. | ||
* API (global) events run for all providers. | ||
* @param {ProviderEvents} eventType The provider event type to listen to | ||
* @param {EventHandler} handler The handler to run on occurrence of the event type | ||
*/ | ||
addHandler<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): 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<T extends ProviderEvents>(eventType: T, handler: EventHandler<T>): 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<T extends ProviderEvents>(eventType: T): EventHandler<T>[]; | ||
/** | ||
* Sets the default provider for flag evaluations and returns a promise that resolves when the provider is ready. | ||
* 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 {Promise<void>} | ||
* @throws Uncaught exceptions thrown by the provider during initialization. | ||
*/ | ||
setProviderAndWait(provider: P): Promise<void>; | ||
/** | ||
* Sets the provider that OpenFeature will use for flag evaluations of providers with the given name. | ||
* A promise is returned that resolves when the provider is ready. | ||
* 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 {Promise<void>} | ||
* @throws Uncaught exceptions thrown by the provider during initialization. | ||
*/ | ||
setProviderAndWait(clientName: string, provider: P): Promise<void>; | ||
/** | ||
* 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 {this} OpenFeature API | ||
*/ | ||
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; | ||
private setAwaitableProvider; | ||
protected getProviderForClient(name?: string): P; | ||
protected buildAndCacheEventEmitterForClient(name?: string): InternalEventEmitter; | ||
private getUnboundEmitters; | ||
private getAssociatedEventEmitters; | ||
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 FlagEvaluationOptions { | ||
@@ -870,3 +245,56 @@ hooks?: Hook[]; | ||
declare class OpenFeatureAPI extends OpenFeatureCommonAPI<Provider> implements ManageContext<OpenFeatureAPI> { | ||
/** | ||
* Transaction context is a mechanism for adding transaction specific context that | ||
* is merged with evaluation context prior to flag evaluation. Examples of potential | ||
* transaction specific context include: a user id, user agent, or request path. | ||
*/ | ||
type TransactionContext = EvaluationContext; | ||
interface ManageTransactionContextPropagator<T> extends TransactionContextPropagator { | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Sets a transaction context propagator on this receiver. The transaction context | ||
* propagator is responsible for persisting context for the duration of a single | ||
* transaction. | ||
* @experimental | ||
* @template T The type of the receiver | ||
* @param {TransactionContextPropagator} transactionContextPropagator The context propagator to be used | ||
* @returns {T} The receiver (this object) | ||
*/ | ||
setTransactionContextPropagator(transactionContextPropagator: TransactionContextPropagator): T; | ||
} | ||
interface TransactionContextPropagator { | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Returns the currently defined transaction context using the registered transaction | ||
* context propagator. | ||
* @experimental | ||
* @returns {TransactionContext} The current transaction context | ||
*/ | ||
getTransactionContext(): TransactionContext; | ||
/** | ||
* EXPERIMENTAL: Transaction context propagation is experimental and subject to change. | ||
* The OpenFeature Enhancement Proposal regarding transaction context can be found [here](https://github.com/open-feature/ofep/pull/32). | ||
* | ||
* Sets the transaction context using the registered transaction context propagator. | ||
* @experimental | ||
* @template R The return value of the callback | ||
* @param {TransactionContext} transactionContext The transaction specific context | ||
* @param {(...args: unknown[]) => R} callback Callback function used to set the transaction context on the stack | ||
* @param {...unknown[]} args Optional arguments that are passed to the callback function | ||
*/ | ||
setTransactionContext<R>(transactionContext: TransactionContext, callback: (...args: unknown[]) => R, ...args: unknown[]): void; | ||
} | ||
declare class NoopTransactionContextPropagator implements TransactionContextPropagator { | ||
getTransactionContext(): EvaluationContext; | ||
setTransactionContext(_: EvaluationContext, callback: () => void): void; | ||
} | ||
declare const NOOP_TRANSACTION_CONTEXT_PROPAGATOR: NoopTransactionContextPropagator; | ||
declare class OpenFeatureAPI extends OpenFeatureCommonAPI<Provider> implements ManageContext<OpenFeatureAPI>, ManageTransactionContextPropagator<OpenFeatureCommonAPI<Provider>> { | ||
private _transactionContextPropagator; | ||
protected _defaultProvider: Provider; | ||
@@ -917,2 +345,10 @@ private constructor(); | ||
getClient(name: string, version: string, context?: EvaluationContext): Client; | ||
/** | ||
* Clears all registered providers and resets the default provider. | ||
* @returns {Promise<void>} | ||
*/ | ||
clearProviders(): Promise<void>; | ||
setTransactionContextPropagator(transactionContextPropagator: TransactionContextPropagator): OpenFeatureCommonAPI<Provider>; | ||
setTransactionContext<R>(transactionContext: TransactionContext, callback: (...args: unknown[]) => R, ...args: unknown[]): void; | ||
getTransactionContext(): TransactionContext; | ||
} | ||
@@ -925,2 +361,2 @@ /** | ||
export { BeforeHookContext, Client, ClientMetadata, CommonEventDetails, CommonProvider, ConfigChangeEvent, DefaultLogger, ErrorCode, ErrorEvent, EvaluationContext, EvaluationContextValue, EvaluationDetails, EvaluationLifeCycle, EventContext, EventDetails, EventHandler, EventMetadata, Eventing, Features, FlagEvaluationOptions, FlagMetadata, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, Hook, HookContext, HookHints, InMemoryProvider, InternalEventEmitter, InvalidContextError, JsonArray, JsonObject, JsonValue, LOG_LEVELS, Logger, ManageContext, ManageLogger, ManageTransactionContextPropagator, Metadata, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, OpenFeatureEventEmitter, Paradigm, ParseError, PrimitiveValue, Provider, ProviderEvents, ProviderMetadata, ProviderStatus, ReadyEvent, ResolutionDetails, ResolutionReason, SafeLogger, StaleEvent, StandardResolutionReasons, TargetingKeyMissingError, TransactionContext, TransactionContextPropagator, TypeMismatchError, isObject, isString, objectOrUndefined, statusMatchesEvent, stringOrUndefined }; | ||
export { Client, Features, FlagEvaluationOptions, InMemoryProvider, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, Provider, TransactionContext, TransactionContextPropagator }; |
{ | ||
"name": "@openfeature/server-sdk", | ||
"version": "1.6.3", | ||
"version": "1.7.0", | ||
"description": "OpenFeature SDK for JavaScript", | ||
@@ -17,7 +17,7 @@ "main": "./dist/cjs/index.js", | ||
"scripts": { | ||
"test": "jest --verbose", | ||
"test": "jest --verbose", | ||
"lint": "eslint ./", | ||
"clean": "shx rm -rf ./dist", | ||
"build:esm": "esbuild src/index.ts --bundle --sourcemap --target=es2016 --platform=node --format=esm --outfile=./dist/esm/index.js --analyze", | ||
"build:cjs": "esbuild src/index.ts --bundle --sourcemap --target=es2016 --platform=node --format=cjs --outfile=./dist/cjs/index.js --analyze", | ||
"build:esm": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2016 --platform=node --format=esm --outfile=./dist/esm/index.js --analyze", | ||
"build:cjs": "esbuild src/index.ts --bundle --external:@openfeature/core --sourcemap --target=es2016 --platform=node --format=cjs --outfile=./dist/cjs/index.js --analyze", | ||
"build:rollup-types": "rollup -c ../../rollup.config.mjs", | ||
@@ -29,3 +29,3 @@ "build": "npm run clean && npm run build:esm && npm run build:cjs && npm run build:rollup-types", | ||
"publish-if-not-exists": "cp $NPM_CONFIG_USERCONFIG .npmrc && if [ \"$(npm show $npm_package_name@$npm_package_version version)\" = \"$(npm run current-version -s)\" ]; then echo 'already published, skipping'; else npm publish --access public; fi", | ||
"docs": "typedoc" | ||
"update-core-peer": "npm install --save-peer --save-exact @openfeature/core@$OPENFEATURE_CORE_VERSION" | ||
}, | ||
@@ -52,9 +52,8 @@ "repository": { | ||
}, | ||
"peerDependencies": { | ||
"@openfeature/core": "0.0.16" | ||
}, | ||
"devDependencies": { | ||
"@openfeature/shared": "*" | ||
}, | ||
"typedoc": { | ||
"displayName": "OpenFeature Server SDK", | ||
"entryPoint": "./src/index.ts" | ||
"@openfeature/core": "0.0.16" | ||
} | ||
} |
@@ -19,8 +19,8 @@ <!-- markdownlint-disable MD033 --> | ||
<!-- x-release-please-start-version --> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.6.3"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.6.3&color=blue&style=for-the-badge" /> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.7.0"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.7.0&color=blue&style=for-the-badge" /> | ||
</a> | ||
<!-- x-release-please-end --> | ||
<br/> | ||
<a href="https://open-feature.github.io/js-sdk/modules/OpenFeature_JS_SDK.html"> | ||
<a href="https://open-feature.github.io/js-sdk/modules/_openfeature_server_sdk.html"> | ||
<img alt="API Reference" src="https://img.shields.io/badge/reference-teal?logo=javascript&logoColor=white" /> | ||
@@ -85,3 +85,3 @@ </a> | ||
See [here](https://open-feature.github.io/js-sdk/modules/OpenFeature_JS_SDK.html) for the complete API documentation. | ||
See [here](https://open-feature.github.io/js-sdk/modules/_openfeature_server_sdk.html) for the complete API documentation. | ||
@@ -317,2 +317,2 @@ ## 🌟 Features | ||
> Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs! | ||
> Built a new hook? [Let us know](https://github.com/open-feature/openfeature.dev/issues/new?assignees=&labels=hook&projects=&template=document-hook.yaml&title=%5BHook%5D%3A+) so we can add it to the docs! |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
316
149861
1
1346