@openfeature/server-sdk
Advanced tools
Comparing version 1.13.5 to 1.14.0
@@ -30,34 +30,11 @@ "use strict"; | ||
OpenFeatureAPI: () => OpenFeatureAPI, | ||
OpenFeatureClient: () => OpenFeatureClient, | ||
OpenFeatureEventEmitter: () => OpenFeatureEventEmitter, | ||
ProviderEvents: () => import_core2.ServerProviderEvents, | ||
ProviderStatus: () => import_core3.ServerProviderStatus | ||
ProviderEvents: () => import_core6.ServerProviderEvents, | ||
ProviderStatus: () => import_core.ServerProviderStatus | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
// src/client/open-feature-client.ts | ||
var import_core7 = require("@openfeature/core"); | ||
// src/open-feature.ts | ||
var import_core6 = require("@openfeature/core"); | ||
// src/events/open-feature-event-emitter.ts | ||
// src/provider/provider.ts | ||
var import_core = require("@openfeature/core"); | ||
var import_node_events = require("events"); | ||
var OpenFeatureEventEmitter = class extends import_core.GenericEventEmitter { | ||
eventEmitter = new import_node_events.EventEmitter({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter.on("error", (err) => { | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
} | ||
}; | ||
// src/events/events.ts | ||
var import_core2 = require("@openfeature/core"); | ||
// src/provider/provider.ts | ||
var import_core3 = require("@openfeature/core"); | ||
// src/provider/no-op-provider.ts | ||
@@ -91,7 +68,7 @@ var REASON_NO_OP = "No-op"; | ||
// src/provider/in-memory-provider/in-memory-provider.ts | ||
var import_core5 = require("@openfeature/core"); | ||
var import_core3 = require("@openfeature/core"); | ||
// src/provider/in-memory-provider/variant-not-found-error.ts | ||
var import_core4 = require("@openfeature/core"); | ||
var VariantFoundError = class _VariantFoundError extends import_core4.OpenFeatureError { | ||
var import_core2 = require("@openfeature/core"); | ||
var VariantFoundError = class _VariantFoundError extends import_core2.OpenFeatureError { | ||
code; | ||
@@ -102,3 +79,3 @@ constructor(message) { | ||
this.name = "VariantFoundError"; | ||
this.code = import_core4.ErrorCode.GENERAL; | ||
this.code = import_core2.ErrorCode.GENERAL; | ||
} | ||
@@ -125,3 +102,3 @@ }; | ||
this._flagConfiguration = { ...flagConfiguration }; | ||
this.events.emit(import_core2.ServerProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
this.events.emit(import_core6.ServerProviderEvents.ConfigurationChanged, { flagsChanged }); | ||
} | ||
@@ -144,8 +121,8 @@ resolveBooleanEvaluation(flagKey, defaultValue, context, logger) { | ||
if (typeof resolutionResult?.value != typeof defaultValue) { | ||
throw new import_core5.TypeMismatchError(); | ||
throw new import_core3.TypeMismatchError(); | ||
} | ||
return resolutionResult; | ||
} catch (error) { | ||
if (!(error instanceof import_core5.OpenFeatureError)) { | ||
throw new import_core5.GeneralError(error?.message || "unknown error"); | ||
if (!(error instanceof import_core3.OpenFeatureError)) { | ||
throw new import_core3.GeneralError(error?.message || "unknown error"); | ||
} | ||
@@ -159,7 +136,7 @@ throw error; | ||
logger?.debug(message); | ||
throw new import_core5.FlagNotFoundError(message); | ||
throw new import_core3.FlagNotFoundError(message); | ||
} | ||
const flagSpec = this._flagConfiguration[flagKey]; | ||
if (flagSpec.disabled) { | ||
return { value: defaultValue, reason: import_core5.StandardResolutionReasons.DISABLED }; | ||
return { value: defaultValue, reason: import_core3.StandardResolutionReasons.DISABLED }; | ||
} | ||
@@ -177,3 +154,3 @@ const isContextEval = ctx && flagSpec?.contextEvaluator; | ||
...variant && { variant }, | ||
reason: isContextEval ? import_core5.StandardResolutionReasons.TARGETING_MATCH : import_core5.StandardResolutionReasons.STATIC | ||
reason: isContextEval ? import_core3.StandardResolutionReasons.TARGETING_MATCH : import_core3.StandardResolutionReasons.STATIC | ||
}; | ||
@@ -183,113 +160,7 @@ } | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback, ...args) { | ||
callback(...args); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/transaction-context/async-local-storage-transaction-context-propagator.ts | ||
var import_async_hooks = require("async_hooks"); | ||
var AsyncLocalStorageTransactionContextPropagator = class { | ||
asyncLocalStorage = new import_async_hooks.AsyncLocalStorage(); | ||
getTransactionContext() { | ||
return this.asyncLocalStorage.getStore() ?? {}; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this.asyncLocalStorage.run(transactionContext, callback, ...args); | ||
} | ||
}; | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class _OpenFeatureAPI extends import_core6.OpenFeatureCommonAPI { | ||
_statusEnumType = import_core3.ServerProviderStatus; | ||
_apiEmitter = new OpenFeatureEventEmitter(); | ||
_defaultProvider = new import_core6.ProviderWrapper(NOOP_PROVIDER, import_core3.ServerProviderStatus.NOT_READY, this._statusEnumType); | ||
_domainScopedProviders = /* @__PURE__ */ new Map(); | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
constructor() { | ||
super("server"); | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* @ignore | ||
* @returns {OpenFeatureAPI} OpenFeature API | ||
*/ | ||
static getInstance() { | ||
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY]; | ||
if (globalApi) { | ||
return globalApi; | ||
} | ||
const instance = new _OpenFeatureAPI(); | ||
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance; | ||
return instance; | ||
} | ||
getProviderStatus(domain) { | ||
if (!domain) { | ||
return this._defaultProvider.status; | ||
} | ||
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status; | ||
} | ||
setContext(context) { | ||
this._context = context; | ||
return this; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
getClient(domainOrContext, versionOrContext, contextOrUndefined) { | ||
const domain = (0, import_core6.stringOrUndefined)(domainOrContext); | ||
const version = (0, import_core6.stringOrUndefined)(versionOrContext); | ||
const context = (0, import_core6.objectOrUndefined)(domainOrContext) ?? (0, import_core6.objectOrUndefined)(versionOrContext) ?? (0, import_core6.objectOrUndefined)(contextOrUndefined); | ||
return new OpenFeatureClient( | ||
() => this.getProviderForClient(domain), | ||
() => this.getProviderStatus(domain), | ||
() => this.buildAndCacheEventEmitterForClient(domain), | ||
() => this._logger, | ||
{ domain, version }, | ||
context | ||
); | ||
} | ||
/** | ||
* 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?.getTransactionContext !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof 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?.message}, returning empty context.`); | ||
this._logger.error(error?.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
var OpenFeature = OpenFeatureAPI.getInstance(); | ||
var import_core7 = require("@openfeature/core"); | ||
// src/client/open-feature-client.ts | ||
// src/client/internal/open-feature-client.ts | ||
var import_core4 = require("@openfeature/core"); | ||
var OpenFeatureClient = class { | ||
@@ -321,3 +192,3 @@ constructor(providerAccessor, providerStatusAccessor, emitterAccessor, globalLogger, options, context = {}) { | ||
this.emitterAccessor().addHandler(eventType, handler); | ||
const shouldRunNow = (0, import_core7.statusMatchesEvent)(eventType, this._providerStatus); | ||
const shouldRunNow = (0, import_core4.statusMatchesEvent)(eventType, this._providerStatus); | ||
if (shouldRunNow) { | ||
@@ -342,3 +213,3 @@ try { | ||
setLogger(logger) { | ||
this._clientLogger = new import_core7.SafeLogger(logger); | ||
this._clientLogger = new import_core4.SafeLogger(logger); | ||
return this; | ||
@@ -436,6 +307,6 @@ } | ||
const frozenContext = await this.beforeHooks(allHooks, hookContext, options); | ||
if (this.providerStatus === import_core3.ServerProviderStatus.NOT_READY) { | ||
throw new import_core7.ProviderNotReadyError("provider has not yet initialized"); | ||
} else if (this.providerStatus === import_core3.ServerProviderStatus.FATAL) { | ||
throw new import_core7.ProviderFatalError("provider is in an irrecoverable error state"); | ||
if (this.providerStatus === import_core.ServerProviderStatus.NOT_READY) { | ||
throw new import_core4.ProviderNotReadyError("provider has not yet initialized"); | ||
} else if (this.providerStatus === import_core.ServerProviderStatus.FATAL) { | ||
throw new import_core4.ProviderFatalError("provider is in an irrecoverable error state"); | ||
} | ||
@@ -448,2 +319,5 @@ const resolution = await resolver.call(this._provider, flagKey, defaultValue, frozenContext, this._logger); | ||
}; | ||
if (evaluationDetails.errorCode) { | ||
throw (0, import_core4.instantiateErrorByErrorCode)(evaluationDetails.errorCode); | ||
} | ||
await this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options); | ||
@@ -453,3 +327,3 @@ return evaluationDetails; | ||
const errorMessage = err?.message; | ||
const errorCode = err?.code || import_core7.ErrorCode.GENERAL; | ||
const errorCode = err?.code || import_core4.ErrorCode.GENERAL; | ||
await this.errorHooks(allHooksReversed, hookContext, err, options); | ||
@@ -460,3 +334,3 @@ return { | ||
value: defaultValue, | ||
reason: import_core7.StandardResolutionReasons.ERROR, | ||
reason: import_core4.StandardResolutionReasons.ERROR, | ||
flagMetadata: Object.freeze({}), | ||
@@ -521,2 +395,146 @@ flagKey | ||
// src/events/open-feature-event-emitter.ts | ||
var import_core5 = require("@openfeature/core"); | ||
var import_node_events = require("events"); | ||
var OpenFeatureEventEmitter = class extends import_core5.GenericEventEmitter { | ||
eventEmitter = new import_node_events.EventEmitter({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter.on("error", (err) => { | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
} | ||
}; | ||
// src/events/events.ts | ||
var import_core6 = require("@openfeature/core"); | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback, ...args) { | ||
callback(...args); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/transaction-context/async-local-storage-transaction-context-propagator.ts | ||
var import_async_hooks = require("async_hooks"); | ||
var AsyncLocalStorageTransactionContextPropagator = class { | ||
asyncLocalStorage = new import_async_hooks.AsyncLocalStorage(); | ||
getTransactionContext() { | ||
return this.asyncLocalStorage.getStore() ?? {}; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this.asyncLocalStorage.run(transactionContext, callback, ...args); | ||
} | ||
}; | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class _OpenFeatureAPI extends import_core7.OpenFeatureCommonAPI { | ||
_statusEnumType = import_core.ServerProviderStatus; | ||
_apiEmitter = new OpenFeatureEventEmitter(); | ||
_defaultProvider = new import_core7.ProviderWrapper( | ||
NOOP_PROVIDER, | ||
import_core.ServerProviderStatus.NOT_READY, | ||
this._statusEnumType | ||
); | ||
_domainScopedProviders = /* @__PURE__ */ new Map(); | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
constructor() { | ||
super("server"); | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* @ignore | ||
* @returns {OpenFeatureAPI} OpenFeature API | ||
*/ | ||
static getInstance() { | ||
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY]; | ||
if (globalApi) { | ||
return globalApi; | ||
} | ||
const instance = new _OpenFeatureAPI(); | ||
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance; | ||
return instance; | ||
} | ||
getProviderStatus(domain) { | ||
if (!domain) { | ||
return this._defaultProvider.status; | ||
} | ||
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status; | ||
} | ||
async setProviderAndWait(domainOrProvider, providerOrUndefined) { | ||
const domain = (0, import_core7.stringOrUndefined)(domainOrProvider); | ||
const provider = domain ? (0, import_core7.objectOrUndefined)(providerOrUndefined) : (0, import_core7.objectOrUndefined)(domainOrProvider); | ||
await this.setAwaitableProvider(domain, provider); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
const domain = (0, import_core7.stringOrUndefined)(clientOrProvider); | ||
const provider = domain ? (0, import_core7.objectOrUndefined)(providerOrUndefined) : (0, import_core7.objectOrUndefined)(clientOrProvider); | ||
const maybePromise = this.setAwaitableProvider(domain, provider); | ||
Promise.resolve(maybePromise).catch((err) => { | ||
this._logger.error("Error during provider initialization:", err); | ||
}); | ||
return this; | ||
} | ||
setContext(context) { | ||
this._context = context; | ||
return this; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
getClient(domainOrContext, versionOrContext, contextOrUndefined) { | ||
const domain = (0, import_core7.stringOrUndefined)(domainOrContext); | ||
const version = (0, import_core7.stringOrUndefined)(versionOrContext); | ||
const context = (0, import_core7.objectOrUndefined)(domainOrContext) ?? (0, import_core7.objectOrUndefined)(versionOrContext) ?? (0, import_core7.objectOrUndefined)(contextOrUndefined); | ||
return new OpenFeatureClient( | ||
() => this.getProviderForClient(domain), | ||
() => this.getProviderStatus(domain), | ||
() => this.buildAndCacheEventEmitterForClient(domain), | ||
() => this._logger, | ||
{ domain, version }, | ||
context | ||
); | ||
} | ||
/** | ||
* 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?.getTransactionContext !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof 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?.message}, returning empty context.`); | ||
this._logger.error(error?.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
var OpenFeature = OpenFeatureAPI.getInstance(); | ||
// src/index.ts | ||
@@ -532,3 +550,2 @@ __reExport(src_exports, require("@openfeature/core"), module.exports); | ||
OpenFeatureAPI, | ||
OpenFeatureClient, | ||
OpenFeatureEventEmitter, | ||
@@ -535,0 +552,0 @@ ProviderEvents, |
@@ -1,35 +0,1 @@ | ||
// src/client/open-feature-client.ts | ||
import { | ||
ErrorCode as ErrorCode2, | ||
ProviderFatalError, | ||
ProviderNotReadyError, | ||
SafeLogger, | ||
StandardResolutionReasons as StandardResolutionReasons2, | ||
statusMatchesEvent | ||
} from "@openfeature/core"; | ||
// src/open-feature.ts | ||
import { | ||
OpenFeatureCommonAPI, | ||
ProviderWrapper, | ||
objectOrUndefined, | ||
stringOrUndefined | ||
} from "@openfeature/core"; | ||
// src/events/open-feature-event-emitter.ts | ||
import { GenericEventEmitter } from "@openfeature/core"; | ||
import { EventEmitter } from "events"; | ||
var OpenFeatureEventEmitter = class extends GenericEventEmitter { | ||
eventEmitter = new EventEmitter({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter.on("error", (err) => { | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
} | ||
}; | ||
// src/events/events.ts | ||
import { ServerProviderEvents } from "@openfeature/core"; | ||
// src/provider/provider.ts | ||
@@ -158,113 +124,20 @@ import { ServerProviderStatus } from "@openfeature/core"; | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback, ...args) { | ||
callback(...args); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/transaction-context/async-local-storage-transaction-context-propagator.ts | ||
import { AsyncLocalStorage } from "async_hooks"; | ||
var AsyncLocalStorageTransactionContextPropagator = class { | ||
asyncLocalStorage = new AsyncLocalStorage(); | ||
getTransactionContext() { | ||
return this.asyncLocalStorage.getStore() ?? {}; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this.asyncLocalStorage.run(transactionContext, callback, ...args); | ||
} | ||
}; | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class _OpenFeatureAPI extends OpenFeatureCommonAPI { | ||
_statusEnumType = ServerProviderStatus; | ||
_apiEmitter = new OpenFeatureEventEmitter(); | ||
_defaultProvider = new ProviderWrapper(NOOP_PROVIDER, ServerProviderStatus.NOT_READY, this._statusEnumType); | ||
_domainScopedProviders = /* @__PURE__ */ new Map(); | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
constructor() { | ||
super("server"); | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* @ignore | ||
* @returns {OpenFeatureAPI} OpenFeature API | ||
*/ | ||
static getInstance() { | ||
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY]; | ||
if (globalApi) { | ||
return globalApi; | ||
} | ||
const instance = new _OpenFeatureAPI(); | ||
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance; | ||
return instance; | ||
} | ||
getProviderStatus(domain) { | ||
if (!domain) { | ||
return this._defaultProvider.status; | ||
} | ||
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status; | ||
} | ||
setContext(context) { | ||
this._context = context; | ||
return this; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
getClient(domainOrContext, versionOrContext, contextOrUndefined) { | ||
const domain = stringOrUndefined(domainOrContext); | ||
const version = stringOrUndefined(versionOrContext); | ||
const context = objectOrUndefined(domainOrContext) ?? objectOrUndefined(versionOrContext) ?? objectOrUndefined(contextOrUndefined); | ||
return new OpenFeatureClient( | ||
() => this.getProviderForClient(domain), | ||
() => this.getProviderStatus(domain), | ||
() => this.buildAndCacheEventEmitterForClient(domain), | ||
() => this._logger, | ||
{ domain, version }, | ||
context | ||
); | ||
} | ||
/** | ||
* 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?.getTransactionContext !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof 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?.message}, returning empty context.`); | ||
this._logger.error(error?.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
var OpenFeature = OpenFeatureAPI.getInstance(); | ||
import { | ||
OpenFeatureCommonAPI, | ||
ProviderWrapper, | ||
objectOrUndefined, | ||
stringOrUndefined | ||
} from "@openfeature/core"; | ||
// src/client/open-feature-client.ts | ||
// src/client/internal/open-feature-client.ts | ||
import { | ||
ErrorCode as ErrorCode2, | ||
ProviderFatalError, | ||
ProviderNotReadyError, | ||
SafeLogger, | ||
StandardResolutionReasons as StandardResolutionReasons2, | ||
instantiateErrorByErrorCode, | ||
statusMatchesEvent | ||
} from "@openfeature/core"; | ||
var OpenFeatureClient = class { | ||
@@ -420,2 +293,5 @@ constructor(providerAccessor, providerStatusAccessor, emitterAccessor, globalLogger, options, context = {}) { | ||
}; | ||
if (evaluationDetails.errorCode) { | ||
throw instantiateErrorByErrorCode(evaluationDetails.errorCode); | ||
} | ||
await this.afterHooks(allHooksReversed, hookContext, evaluationDetails, options); | ||
@@ -491,2 +367,146 @@ return evaluationDetails; | ||
// src/events/open-feature-event-emitter.ts | ||
import { GenericEventEmitter } from "@openfeature/core"; | ||
import { EventEmitter } from "events"; | ||
var OpenFeatureEventEmitter = class extends GenericEventEmitter { | ||
eventEmitter = new EventEmitter({ captureRejections: true }); | ||
constructor() { | ||
super(); | ||
this.eventEmitter.on("error", (err) => { | ||
this._logger?.error("Error running event handler:", err); | ||
}); | ||
} | ||
}; | ||
// src/events/events.ts | ||
import { ServerProviderEvents } from "@openfeature/core"; | ||
// src/transaction-context/no-op-transaction-context-propagator.ts | ||
var NoopTransactionContextPropagator = class { | ||
getTransactionContext() { | ||
return {}; | ||
} | ||
setTransactionContext(_, callback, ...args) { | ||
callback(...args); | ||
} | ||
}; | ||
var NOOP_TRANSACTION_CONTEXT_PROPAGATOR = new NoopTransactionContextPropagator(); | ||
// src/transaction-context/async-local-storage-transaction-context-propagator.ts | ||
import { AsyncLocalStorage } from "async_hooks"; | ||
var AsyncLocalStorageTransactionContextPropagator = class { | ||
asyncLocalStorage = new AsyncLocalStorage(); | ||
getTransactionContext() { | ||
return this.asyncLocalStorage.getStore() ?? {}; | ||
} | ||
setTransactionContext(transactionContext, callback, ...args) { | ||
this.asyncLocalStorage.run(transactionContext, callback, ...args); | ||
} | ||
}; | ||
// src/open-feature.ts | ||
var GLOBAL_OPENFEATURE_API_KEY = Symbol.for("@openfeature/js-sdk/api"); | ||
var _globalThis = globalThis; | ||
var OpenFeatureAPI = class _OpenFeatureAPI extends OpenFeatureCommonAPI { | ||
_statusEnumType = ServerProviderStatus; | ||
_apiEmitter = new OpenFeatureEventEmitter(); | ||
_defaultProvider = new ProviderWrapper( | ||
NOOP_PROVIDER, | ||
ServerProviderStatus.NOT_READY, | ||
this._statusEnumType | ||
); | ||
_domainScopedProviders = /* @__PURE__ */ new Map(); | ||
_createEventEmitter = () => new OpenFeatureEventEmitter(); | ||
_transactionContextPropagator = NOOP_TRANSACTION_CONTEXT_PROPAGATOR; | ||
constructor() { | ||
super("server"); | ||
} | ||
/** | ||
* Gets a singleton instance of the OpenFeature API. | ||
* @ignore | ||
* @returns {OpenFeatureAPI} OpenFeature API | ||
*/ | ||
static getInstance() { | ||
const globalApi = _globalThis[GLOBAL_OPENFEATURE_API_KEY]; | ||
if (globalApi) { | ||
return globalApi; | ||
} | ||
const instance = new _OpenFeatureAPI(); | ||
_globalThis[GLOBAL_OPENFEATURE_API_KEY] = instance; | ||
return instance; | ||
} | ||
getProviderStatus(domain) { | ||
if (!domain) { | ||
return this._defaultProvider.status; | ||
} | ||
return this._domainScopedProviders.get(domain)?.status ?? this._defaultProvider.status; | ||
} | ||
async setProviderAndWait(domainOrProvider, providerOrUndefined) { | ||
const domain = stringOrUndefined(domainOrProvider); | ||
const provider = domain ? objectOrUndefined(providerOrUndefined) : objectOrUndefined(domainOrProvider); | ||
await this.setAwaitableProvider(domain, provider); | ||
} | ||
setProvider(clientOrProvider, providerOrUndefined) { | ||
const domain = stringOrUndefined(clientOrProvider); | ||
const provider = domain ? objectOrUndefined(providerOrUndefined) : objectOrUndefined(clientOrProvider); | ||
const maybePromise = this.setAwaitableProvider(domain, provider); | ||
Promise.resolve(maybePromise).catch((err) => { | ||
this._logger.error("Error during provider initialization:", err); | ||
}); | ||
return this; | ||
} | ||
setContext(context) { | ||
this._context = context; | ||
return this; | ||
} | ||
getContext() { | ||
return this._context; | ||
} | ||
getClient(domainOrContext, versionOrContext, contextOrUndefined) { | ||
const domain = stringOrUndefined(domainOrContext); | ||
const version = stringOrUndefined(versionOrContext); | ||
const context = objectOrUndefined(domainOrContext) ?? objectOrUndefined(versionOrContext) ?? objectOrUndefined(contextOrUndefined); | ||
return new OpenFeatureClient( | ||
() => this.getProviderForClient(domain), | ||
() => this.getProviderStatus(domain), | ||
() => this.buildAndCacheEventEmitterForClient(domain), | ||
() => this._logger, | ||
{ domain, version }, | ||
context | ||
); | ||
} | ||
/** | ||
* 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?.getTransactionContext !== "function") { | ||
this._logger.error(`${baseMessage}: getTransactionContext is not a function.`); | ||
} else if (typeof 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?.message}, returning empty context.`); | ||
this._logger.error(error?.stack); | ||
return {}; | ||
} | ||
} | ||
}; | ||
var OpenFeature = OpenFeatureAPI.getInstance(); | ||
// src/index.ts | ||
@@ -501,3 +521,2 @@ export * from "@openfeature/core"; | ||
OpenFeatureAPI, | ||
OpenFeatureClient, | ||
OpenFeatureEventEmitter, | ||
@@ -504,0 +523,0 @@ ServerProviderEvents as ProviderEvents, |
@@ -1,3 +0,2 @@ | ||
import * as _openfeature_core from '@openfeature/core'; | ||
import { BaseHook, FlagValue, EvaluationContext, HookHints, EvaluationDetails, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, EventHandler, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core'; | ||
import { BaseHook, FlagValue, EvaluationContext, HookHints, EvaluationDetails, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core'; | ||
export * from '@openfeature/core'; | ||
@@ -213,3 +212,3 @@ export { ServerProviderEvents as ProviderEvents, ServerProviderStatus as ProviderStatus } from '@openfeature/core'; | ||
declare class OpenFeatureEventEmitter extends GenericEventEmitter<ServerProviderEvents> { | ||
protected readonly eventEmitter: EventEmitter; | ||
protected readonly eventEmitter: EventEmitter<[never]>; | ||
constructor(); | ||
@@ -227,57 +226,2 @@ } | ||
/** | ||
* The InternalEventEmitter is not exported publicly and should only be used within the SDK. It extends the | ||
* OpenFeatureEventEmitter to include additional properties that can be included | ||
* in the event details. | ||
*/ | ||
declare abstract class InternalEventEmitter extends GenericEventEmitter<ServerProviderEvents> { | ||
} | ||
type OpenFeatureClientOptions = { | ||
/** | ||
* @deprecated Use `domain` instead. | ||
*/ | ||
name?: string; | ||
domain?: string; | ||
version?: string; | ||
}; | ||
declare class OpenFeatureClient implements Client, ManageContext<OpenFeatureClient> { | ||
private readonly providerAccessor; | ||
private readonly providerStatusAccessor; | ||
private readonly emitterAccessor; | ||
private readonly globalLogger; | ||
private readonly options; | ||
private _context; | ||
private _hooks; | ||
private _clientLogger?; | ||
constructor(providerAccessor: () => Provider, providerStatusAccessor: () => ServerProviderStatus, emitterAccessor: () => InternalEventEmitter, globalLogger: () => Logger, options: OpenFeatureClientOptions, context?: EvaluationContext); | ||
get metadata(): ClientMetadata; | ||
get providerStatus(): ServerProviderStatus; | ||
addHandler(eventType: ServerProviderEvents, handler: EventHandler): void; | ||
removeHandler(eventType: ServerProviderEvents, handler: EventHandler): void; | ||
getHandlers(eventType: ServerProviderEvents): EventHandler<ServerProviderEvents | _openfeature_core.AllProviderEvents>[]; | ||
setLogger(logger: Logger): OpenFeatureClient; | ||
setContext(context: EvaluationContext): OpenFeatureClient; | ||
getContext(): EvaluationContext; | ||
addHooks(...hooks: Hook[]): OpenFeatureClient; | ||
getHooks(): Hook[]; | ||
clearHooks(): OpenFeatureClient; | ||
getBooleanValue(flagKey: string, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<boolean>; | ||
getBooleanDetails(flagKey: string, defaultValue: boolean, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<boolean>>; | ||
getStringValue<T extends string = string>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>; | ||
getStringDetails<T extends string = string>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>; | ||
getNumberValue<T extends number = number>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>; | ||
getNumberDetails<T extends number = number>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>; | ||
getObjectValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<T>; | ||
getObjectDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, context?: EvaluationContext, options?: FlagEvaluationOptions): Promise<EvaluationDetails<T>>; | ||
private evaluate; | ||
private beforeHooks; | ||
private afterHooks; | ||
private errorHooks; | ||
private finallyHooks; | ||
private get _provider(); | ||
private get _providerStatus(); | ||
private get _logger(); | ||
} | ||
/** | ||
* Transaction context is a mechanism for adding transaction specific context that | ||
@@ -364,2 +308,37 @@ * is merged with evaluation context prior to flag evaluation. Examples of potential | ||
private getProviderStatus; | ||
/** | ||
* Sets the default provider for flag evaluations and returns a promise that resolves when the provider is ready. | ||
* This provider will be used by domainless clients and clients associated with domains to which no provider is bound. | ||
* Setting a provider supersedes the current provider used in new and existing unbound clients. | ||
* @param {Provider} provider The provider responsible for flag evaluations. | ||
* @returns {Promise<void>} | ||
* @throws Uncaught exceptions thrown by the provider during initialization. | ||
*/ | ||
setProviderAndWait(provider: Provider): Promise<void>; | ||
/** | ||
* Sets the provider that OpenFeature will use for flag evaluations on clients bound to the same domain. | ||
* A promise is returned that resolves when the provider is ready. | ||
* Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. | ||
* @param {string} domain The name to identify the client | ||
* @param {Provider} provider The provider responsible for flag evaluations. | ||
* @returns {Promise<void>} | ||
* @throws Uncaught exceptions thrown by the provider during initialization. | ||
*/ | ||
setProviderAndWait(domain: string, provider: Provider): Promise<void>; | ||
/** | ||
* Sets the default provider for flag evaluations. | ||
* This provider will be used by domainless clients and clients associated with domains to which no provider is bound. | ||
* Setting a provider supersedes the current provider used in new and existing unbound clients. | ||
* @param {Provider} provider The provider responsible for flag evaluations. | ||
* @returns {this} OpenFeature API | ||
*/ | ||
setProvider(provider: Provider): this; | ||
/** | ||
* Sets the provider for flag evaluations of providers with the given name. | ||
* Setting a provider supersedes the current provider used in new and existing clients bound to the same domain. | ||
* @param {string} domain The name to identify the client | ||
* @param {Provider} provider The provider responsible for flag evaluations. | ||
* @returns {this} OpenFeature API | ||
*/ | ||
setProvider(domain: string, provider: Provider): this; | ||
setContext(context: EvaluationContext): this; | ||
@@ -417,2 +396,2 @@ getContext(): EvaluationContext; | ||
export { AsyncLocalStorageTransactionContextPropagator, Client, Features, FlagEvaluationOptions, Hook, InMemoryProvider, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureEventEmitter, Provider, TransactionContext, TransactionContextPropagator }; | ||
export { AsyncLocalStorageTransactionContextPropagator, Client, Features, FlagEvaluationOptions, Hook, InMemoryProvider, ManageTransactionContextPropagator, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter, Provider, TransactionContext, TransactionContextPropagator }; |
{ | ||
"name": "@openfeature/server-sdk", | ||
"version": "1.13.5", | ||
"version": "1.14.0", | ||
"description": "OpenFeature SDK for JavaScript", | ||
@@ -48,10 +48,10 @@ "main": "./dist/cjs/index.js", | ||
"engines": { | ||
"node": ">=16" | ||
"node": ">=18" | ||
}, | ||
"peerDependencies": { | ||
"@openfeature/core": "1.1.0" | ||
"@openfeature/core": "1.2.0" | ||
}, | ||
"devDependencies": { | ||
"@openfeature/core": "1.1.0" | ||
"@openfeature/core": "1.2.0" | ||
} | ||
} |
@@ -19,4 +19,4 @@ <!-- markdownlint-disable MD033 --> | ||
<!-- x-release-please-start-version --> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.13.5"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.13.5&color=blue&style=for-the-badge" /> | ||
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.14.0"> | ||
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.14.0&color=blue&style=for-the-badge" /> | ||
</a> | ||
@@ -48,3 +48,3 @@ <!-- x-release-please-end --> | ||
- Node.js version 16+ | ||
- Node.js version 18+ | ||
@@ -59,2 +59,5 @@ ### Install | ||
> [!TIP] | ||
> This SDK is designed to run in Node.JS. If you're interested in browser support, check out the [Web SDK](https://openfeature.dev/docs/reference/technologies/client/web/). | ||
#### yarn | ||
@@ -164,2 +167,5 @@ | ||
Context is merged by the SDK before a flag evaluation occurs. | ||
The merge order is defined [here](https://openfeature.dev/specification/sections/evaluation-context#requirement-323) in the OpenFeature specification. | ||
### Hooks | ||
@@ -166,0 +172,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
178432
1417
384