Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@openfeature/server-sdk

Package Overview
Dependencies
Maintainers
4
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@openfeature/server-sdk - npm Package Compare versions

Comparing version
1.20.1
to
1.20.2
+54
-267
dist/cjs/index.js

@@ -61,7 +61,4 @@ "use strict";

__export(index_exports, {
AggregateError: () => AggregateError,
AsyncLocalStorageTransactionContextPropagator: () => AsyncLocalStorageTransactionContextPropagator,
BaseEvaluationStrategy: () => BaseEvaluationStrategy,
ComparisonStrategy: () => ComparisonStrategy,
ErrorWithCode: () => ErrorWithCode,
FirstMatchStrategy: () => FirstMatchStrategy,

@@ -77,5 +74,3 @@ FirstSuccessfulStrategy: () => FirstSuccessfulStrategy,

ProviderEvents: () => import_core6.ServerProviderEvents,
ProviderStatus: () => import_core.ServerProviderStatus,
constructAggregateError: () => constructAggregateError,
throwAggregateErrorFromPromiseResults: () => throwAggregateErrorFromPromiseResults
ProviderStatus: () => import_core.ServerProviderStatus
});

@@ -209,8 +204,26 @@ module.exports = __toCommonJS(index_exports);

// src/provider/multi-provider/multi-provider.ts
var import_core9 = require("@openfeature/core");
var import_core7 = require("@openfeature/core");
// src/provider/multi-provider/strategies.ts
var import_core4 = require("@openfeature/core");
var FirstMatchStrategy = class extends import_core4.BaseFirstMatchStrategy {
constructor() {
super(import_core.ServerProviderStatus);
}
};
var FirstSuccessfulStrategy = class extends import_core4.BaseFirstSuccessfulStrategy {
constructor() {
super(import_core.ServerProviderStatus);
}
};
var ComparisonStrategy = class extends import_core4.BaseComparisonStrategy {
constructor(fallbackProvider, onMismatch) {
super(import_core.ServerProviderStatus, fallbackProvider, onMismatch);
}
};
// src/events/open-feature-event-emitter.ts
var import_core4 = require("@openfeature/core");
var import_core5 = require("@openfeature/core");
var import_node_events = require("node:events");
var OpenFeatureEventEmitter = class extends import_core4.GenericEventEmitter {
var OpenFeatureEventEmitter = class extends import_core5.GenericEventEmitter {
constructor() {

@@ -226,36 +239,4 @@ super();

// src/provider/multi-provider/errors.ts
var import_core5 = require("@openfeature/core");
var ErrorWithCode = class extends import_core5.OpenFeatureError {
constructor(code, message) {
super(message);
this.code = code;
}
};
var AggregateError = class extends import_core5.GeneralError {
constructor(message, originalErrors) {
super(message);
this.originalErrors = originalErrors;
}
};
var constructAggregateError = (providerErrors) => {
const errorsWithSource = providerErrors.map(({ providerName, error }) => {
return { source: providerName, error };
}).flat();
return new AggregateError(
`Provider errors occurred: ${errorsWithSource[0].source}: ${errorsWithSource[0].error}`,
errorsWithSource
);
};
var throwAggregateErrorFromPromiseResults = (result, providerEntries) => {
const errors = result.map((r, i) => {
if (r.status === "rejected") {
return { error: r.reason, providerName: providerEntries[i].name };
}
return null;
}).filter((val) => Boolean(val));
if (errors.length) {
throw constructAggregateError(errors);
}
};
// src/events/events.ts
var import_core6 = require("@openfeature/core");

@@ -319,192 +300,5 @@ // src/provider/multi-provider/hook-executor.ts

// src/events/events.ts
var import_core6 = require("@openfeature/core");
// src/provider/multi-provider/status-tracker.ts
var StatusTracker = class {
constructor(events) {
this.events = events;
this.providerStatuses = {};
}
wrapEventHandler(providerEntry) {
var _a, _b, _c, _d;
const provider = providerEntry.provider;
(_a = provider.events) == null ? void 0 : _a.addHandler(import_core6.ServerProviderEvents.Error, (details) => {
this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.ERROR, details);
});
(_b = provider.events) == null ? void 0 : _b.addHandler(import_core6.ServerProviderEvents.Stale, (details) => {
this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.STALE, details);
});
(_c = provider.events) == null ? void 0 : _c.addHandler(import_core6.ServerProviderEvents.ConfigurationChanged, (details) => {
this.events.emit(import_core6.ServerProviderEvents.ConfigurationChanged, details);
});
(_d = provider.events) == null ? void 0 : _d.addHandler(import_core6.ServerProviderEvents.Ready, (details) => {
this.changeProviderStatus(providerEntry.name, import_core.ServerProviderStatus.READY, details);
});
}
providerStatus(name) {
return this.providerStatuses[name];
}
getStatusFromProviderStatuses() {
const statuses = Object.values(this.providerStatuses);
if (statuses.includes(import_core.ServerProviderStatus.FATAL)) {
return import_core.ServerProviderStatus.FATAL;
} else if (statuses.includes(import_core.ServerProviderStatus.NOT_READY)) {
return import_core.ServerProviderStatus.NOT_READY;
} else if (statuses.includes(import_core.ServerProviderStatus.ERROR)) {
return import_core.ServerProviderStatus.ERROR;
} else if (statuses.includes(import_core.ServerProviderStatus.STALE)) {
return import_core.ServerProviderStatus.STALE;
}
return import_core.ServerProviderStatus.READY;
}
changeProviderStatus(name, status, details) {
const currentStatus = this.getStatusFromProviderStatuses();
this.providerStatuses[name] = status;
const newStatus = this.getStatusFromProviderStatuses();
if (currentStatus !== newStatus) {
if (newStatus === import_core.ServerProviderStatus.FATAL || newStatus === import_core.ServerProviderStatus.ERROR) {
this.events.emit(import_core6.ServerProviderEvents.Error, details);
} else if (newStatus === import_core.ServerProviderStatus.STALE) {
this.events.emit(import_core6.ServerProviderEvents.Stale, details);
} else if (newStatus === import_core.ServerProviderStatus.READY) {
this.events.emit(import_core6.ServerProviderEvents.Ready, details);
}
}
}
};
// src/provider/multi-provider/strategies/base-evaluation-strategy.ts
var BaseEvaluationStrategy = class {
constructor() {
this.runMode = "sequential";
}
shouldEvaluateThisProvider(strategyContext, _evalContext) {
if (strategyContext.providerStatus === import_core.ServerProviderStatus.NOT_READY || strategyContext.providerStatus === import_core.ServerProviderStatus.FATAL) {
return false;
}
return true;
}
shouldEvaluateNextProvider(_strategyContext, _context, _result) {
return true;
}
shouldTrackWithThisProvider(strategyContext, _context, _trackingEventName, _trackingEventDetails) {
if (strategyContext.providerStatus === import_core.ServerProviderStatus.NOT_READY || strategyContext.providerStatus === import_core.ServerProviderStatus.FATAL) {
return false;
}
return true;
}
hasError(resolution) {
return "thrownError" in resolution || !!resolution.details.errorCode;
}
hasErrorWithCode(resolution, code) {
var _a;
return "thrownError" in resolution ? ((_a = resolution.thrownError) == null ? void 0 : _a.code) === code : resolution.details.errorCode === code;
}
collectProviderErrors(resolutions) {
var _a;
const errors = [];
for (const resolution of resolutions) {
if ("thrownError" in resolution) {
errors.push({ providerName: resolution.providerName, error: resolution.thrownError });
} else if (resolution.details.errorCode) {
errors.push({
providerName: resolution.providerName,
error: new ErrorWithCode(resolution.details.errorCode, (_a = resolution.details.errorMessage) != null ? _a : "unknown error")
});
}
}
return { errors };
}
resolutionToFinalResult(resolution) {
return { details: resolution.details, provider: resolution.provider, providerName: resolution.providerName };
}
};
// src/provider/multi-provider/strategies/first-match-strategy.ts
var import_core7 = require("@openfeature/core");
var FirstMatchStrategy = class extends BaseEvaluationStrategy {
shouldEvaluateNextProvider(strategyContext, context, result) {
if (this.hasErrorWithCode(result, import_core7.ErrorCode.FLAG_NOT_FOUND)) {
return true;
}
if (this.hasError(result)) {
return false;
}
return false;
}
determineFinalResult(strategyContext, context, resolutions) {
const finalResolution = resolutions[resolutions.length - 1];
if (this.hasError(finalResolution)) {
return this.collectProviderErrors(resolutions);
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/strategies/first-successful-strategy.ts
var FirstSuccessfulStrategy = class extends BaseEvaluationStrategy {
shouldEvaluateNextProvider(strategyContext, context, result) {
return this.hasError(result);
}
determineFinalResult(strategyContext, context, resolutions) {
const finalResolution = resolutions[resolutions.length - 1];
if (this.hasError(finalResolution)) {
return this.collectProviderErrors(resolutions);
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/strategies/comparison-strategy.ts
var import_core8 = require("@openfeature/core");
var ComparisonStrategy = class extends BaseEvaluationStrategy {
constructor(fallbackProvider, onMismatch) {
super();
this.fallbackProvider = fallbackProvider;
this.onMismatch = onMismatch;
this.runMode = "parallel";
}
determineFinalResult(strategyContext, context, resolutions) {
var _a;
let value;
let fallbackResolution;
let finalResolution;
let mismatch = false;
for (const [i, resolution] of resolutions.entries()) {
if (this.hasError(resolution)) {
return this.collectProviderErrors(resolutions);
}
if (resolution.provider === this.fallbackProvider) {
fallbackResolution = resolution;
}
if (i === 0) {
finalResolution = resolution;
}
if (typeof value !== "undefined" && value !== resolution.details.value) {
mismatch = true;
} else {
value = resolution.details.value;
}
}
if (!fallbackResolution) {
throw new import_core8.GeneralError("Fallback provider not found in resolution results");
}
if (!finalResolution) {
throw new import_core8.GeneralError("Final resolution not found in resolution results");
}
if (mismatch) {
(_a = this.onMismatch) == null ? void 0 : _a.call(this, resolutions);
return {
details: fallbackResolution.details,
provider: fallbackResolution.provider
};
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/multi-provider.ts
var MultiProvider = class _MultiProvider {
constructor(constructorProviders, evaluationStrategy = new FirstMatchStrategy(), logger = new import_core9.DefaultLogger()) {
constructor(constructorProviders, evaluationStrategy = new FirstMatchStrategy(), logger = new import_core7.DefaultLogger()) {
this.constructorProviders = constructorProviders;

@@ -519,3 +313,3 @@ this.evaluationStrategy = evaluationStrategy;

this.providerEntriesByName = {};
this.statusTracker = new StatusTracker(this.events);
this.statusTracker = new import_core7.StatusTracker(this.events, import_core.ServerProviderStatus, import_core6.ServerProviderEvents);
this.hookExecutor = new HookExecutor(this.logger);

@@ -562,3 +356,3 @@ this.registerProviders(constructorProviders);

);
throwAggregateErrorFromPromiseResults(result, this.providerEntries);
(0, import_core7.throwAggregateErrorFromPromiseResults)(result, this.providerEntries);
});

@@ -572,3 +366,3 @@ }

}));
throwAggregateErrorFromPromiseResults(result, this.providerEntries);
(0, import_core7.throwAggregateErrorFromPromiseResults)(result, this.providerEntries);
});

@@ -594,3 +388,3 @@ }

if (!hookContext || !hookHints) {
throw new import_core9.GeneralError("Hook context not available for evaluation");
throw new import_core7.GeneralError("Hook context not available for evaluation");
}

@@ -620,6 +414,6 @@ const tasks = [];

if ((_a = finalResult.errors) == null ? void 0 : _a.length) {
throw constructAggregateError(finalResult.errors);
throw (0, import_core7.constructAggregateError)(finalResult.errors);
}
if (!finalResult.details) {
throw new import_core9.GeneralError("No result was returned from any provider");
throw new import_core7.GeneralError("No result was returned from any provider");
}

@@ -703,3 +497,3 @@ return finalResult.details;

default:
throw new import_core9.GeneralError("Invalid flag evaluation type");
throw new import_core7.GeneralError("Invalid flag evaluation type");
}

@@ -749,3 +543,3 @@ });

const errorMessage = err == null ? void 0 : err.message;
const errorCode = (err == null ? void 0 : err.code) || import_core9.ErrorCode.GENERAL;
const errorCode = (err == null ? void 0 : err.code) || import_core7.ErrorCode.GENERAL;
return {

@@ -755,3 +549,3 @@ errorCode,

value: defaultValue,
reason: import_core9.StandardResolutionReasons.ERROR,
reason: import_core7.StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze(flagMetadata),

@@ -764,6 +558,6 @@ flagKey

// src/open-feature.ts
var import_core11 = require("@openfeature/core");
var import_core9 = require("@openfeature/core");
// src/client/internal/open-feature-client.ts
var import_core10 = require("@openfeature/core");
var import_core8 = require("@openfeature/core");
var OpenFeatureClient = class {

@@ -798,3 +592,3 @@ constructor(providerAccessor, providerStatusAccessor, emitterAccessor, apiContextAccessor, apiHooksAccessor, transactionContextAccessor, globalLogger, options, context = {}) {

this.emitterAccessor().addHandler(eventType, handler);
const shouldRunNow = (0, import_core10.statusMatchesEvent)(eventType, this._providerStatus);
const shouldRunNow = (0, import_core8.statusMatchesEvent)(eventType, this._providerStatus);
if (shouldRunNow) {

@@ -824,3 +618,3 @@ try {

setLogger(logger) {
this._clientLogger = new import_core10.SafeLogger(logger);
this._clientLogger = new import_core8.SafeLogger(logger);
return this;

@@ -935,3 +729,3 @@ }

logger: this._logger,
hookData: new import_core10.MapHookData()
hookData: new import_core8.MapHookData()
})

@@ -949,3 +743,3 @@ );

if (resolutionDetails.errorCode) {
const err = (0, import_core10.instantiateErrorByErrorCode)(resolutionDetails.errorCode, resolutionDetails.errorMessage);
const err = (0, import_core8.instantiateErrorByErrorCode)(resolutionDetails.errorCode, resolutionDetails.errorMessage);
yield this.errorHooks(allHooksReversed, hookContexts, err, options);

@@ -976,5 +770,3 @@ evaluationDetails = this.getErrorEvaluationDetails(flagKey, defaultValue, err, resolutionDetails.flagMetadata);

Object.assign(accumulatedContext, hookResult);
for (let i = 0; i < hooks.length; i++) {
Object.assign(hookContexts[hookContextIndex].context, accumulatedContext);
}
Object.assign(hookContext.context, accumulatedContext);
}

@@ -1042,5 +834,5 @@ }

if (this.providerStatus === import_core.ServerProviderStatus.NOT_READY) {
throw new import_core10.ProviderNotReadyError("provider has not yet initialized");
throw new import_core8.ProviderNotReadyError("provider has not yet initialized");
} else if (this.providerStatus === import_core.ServerProviderStatus.FATAL) {
throw new import_core10.ProviderFatalError("provider is in an irrecoverable error state");
throw new import_core8.ProviderFatalError("provider is in an irrecoverable error state");
}

@@ -1050,3 +842,3 @@ }

const errorMessage = err == null ? void 0 : err.message;
const errorCode = (err == null ? void 0 : err.code) || import_core10.ErrorCode.GENERAL;
const errorCode = (err == null ? void 0 : err.code) || import_core8.ErrorCode.GENERAL;
return {

@@ -1056,3 +848,3 @@ errorCode,

value: defaultValue,
reason: import_core10.StandardResolutionReasons.ERROR,
reason: import_core8.StandardResolutionReasons.ERROR,
flagMetadata: Object.freeze(flagMetadata),

@@ -1093,3 +885,3 @@ flagKey

var _globalThis = globalThis;
var OpenFeatureAPI = class _OpenFeatureAPI extends import_core11.OpenFeatureCommonAPI {
var OpenFeatureAPI = class _OpenFeatureAPI extends import_core9.OpenFeatureCommonAPI {
constructor() {

@@ -1099,3 +891,3 @@ super("server");

this._apiEmitter = new OpenFeatureEventEmitter();
this._defaultProvider = new import_core11.ProviderWrapper(
this._defaultProvider = new import_core9.ProviderWrapper(
NOOP_PROVIDER,

@@ -1132,4 +924,4 @@ import_core.ServerProviderStatus.NOT_READY,

return __async(this, null, function* () {
const domain = (0, import_core11.stringOrUndefined)(domainOrProvider);
const provider = domain ? (0, import_core11.objectOrUndefined)(providerOrUndefined) : (0, import_core11.objectOrUndefined)(domainOrProvider);
const domain = (0, import_core9.stringOrUndefined)(domainOrProvider);
const provider = domain ? (0, import_core9.objectOrUndefined)(providerOrUndefined) : (0, import_core9.objectOrUndefined)(domainOrProvider);
yield this.setAwaitableProvider(domain, provider);

@@ -1139,4 +931,4 @@ });

setProvider(clientOrProvider, providerOrUndefined) {
const domain = (0, import_core11.stringOrUndefined)(clientOrProvider);
const provider = domain ? (0, import_core11.objectOrUndefined)(providerOrUndefined) : (0, import_core11.objectOrUndefined)(clientOrProvider);
const domain = (0, import_core9.stringOrUndefined)(clientOrProvider);
const provider = domain ? (0, import_core9.objectOrUndefined)(providerOrUndefined) : (0, import_core9.objectOrUndefined)(clientOrProvider);
const maybePromise = this.setAwaitableProvider(domain, provider);

@@ -1160,5 +952,5 @@ Promise.resolve(maybePromise).catch((err) => {

var _a, _b;
const domain = (0, import_core11.stringOrUndefined)(domainOrContext);
const version = (0, import_core11.stringOrUndefined)(versionOrContext);
const context = (_b = (_a = (0, import_core11.objectOrUndefined)(domainOrContext)) != null ? _a : (0, import_core11.objectOrUndefined)(versionOrContext)) != null ? _b : (0, import_core11.objectOrUndefined)(contextOrUndefined);
const domain = (0, import_core9.stringOrUndefined)(domainOrContext);
const version = (0, import_core9.stringOrUndefined)(versionOrContext);
const context = (_b = (_a = (0, import_core9.objectOrUndefined)(domainOrContext)) != null ? _a : (0, import_core9.objectOrUndefined)(versionOrContext)) != null ? _b : (0, import_core9.objectOrUndefined)(contextOrUndefined);
return new OpenFeatureClient(

@@ -1214,7 +1006,4 @@ () => this.getProviderForClient(domain),

0 && (module.exports = {
AggregateError,
AsyncLocalStorageTransactionContextPropagator,
BaseEvaluationStrategy,
ComparisonStrategy,
ErrorWithCode,
FirstMatchStrategy,

@@ -1231,6 +1020,4 @@ FirstSuccessfulStrategy,

ProviderStatus,
constructAggregateError,
throwAggregateErrorFromPromiseResults,
...require("@openfeature/core")
});
//# sourceMappingURL=index.js.map

@@ -42,5 +42,3 @@ var __defProp = Object.defineProperty;

// src/provider/provider.ts
import {
ServerProviderStatus
} from "@openfeature/core";
import { ServerProviderStatus } from "@openfeature/core";

@@ -175,4 +173,34 @@ // src/provider/no-op-provider.ts

// src/provider/multi-provider/multi-provider.ts
import { DefaultLogger, ErrorCode as ErrorCode3, GeneralError as GeneralError4, StandardResolutionReasons as StandardResolutionReasons2 } from "@openfeature/core";
import {
DefaultLogger,
ErrorCode as ErrorCode2,
GeneralError as GeneralError2,
StandardResolutionReasons as StandardResolutionReasons2,
constructAggregateError,
throwAggregateErrorFromPromiseResults,
StatusTracker
} from "@openfeature/core";
// src/provider/multi-provider/strategies.ts
import {
BaseFirstMatchStrategy,
BaseFirstSuccessfulStrategy,
BaseComparisonStrategy
} from "@openfeature/core";
var FirstMatchStrategy = class extends BaseFirstMatchStrategy {
constructor() {
super(ServerProviderStatus);
}
};
var FirstSuccessfulStrategy = class extends BaseFirstSuccessfulStrategy {
constructor() {
super(ServerProviderStatus);
}
};
var ComparisonStrategy = class extends BaseComparisonStrategy {
constructor(fallbackProvider, onMismatch) {
super(ServerProviderStatus, fallbackProvider, onMismatch);
}
};
// src/events/open-feature-event-emitter.ts

@@ -192,36 +220,4 @@ import { GenericEventEmitter } from "@openfeature/core";

// src/provider/multi-provider/errors.ts
import { GeneralError as GeneralError2, OpenFeatureError as OpenFeatureError3 } from "@openfeature/core";
var ErrorWithCode = class extends OpenFeatureError3 {
constructor(code, message) {
super(message);
this.code = code;
}
};
var AggregateError = class extends GeneralError2 {
constructor(message, originalErrors) {
super(message);
this.originalErrors = originalErrors;
}
};
var constructAggregateError = (providerErrors) => {
const errorsWithSource = providerErrors.map(({ providerName, error }) => {
return { source: providerName, error };
}).flat();
return new AggregateError(
`Provider errors occurred: ${errorsWithSource[0].source}: ${errorsWithSource[0].error}`,
errorsWithSource
);
};
var throwAggregateErrorFromPromiseResults = (result, providerEntries) => {
const errors = result.map((r, i) => {
if (r.status === "rejected") {
return { error: r.reason, providerName: providerEntries[i].name };
}
return null;
}).filter((val) => Boolean(val));
if (errors.length) {
throw constructAggregateError(errors);
}
};
// src/events/events.ts
import { ServerProviderEvents } from "@openfeature/core";

@@ -285,189 +281,2 @@ // src/provider/multi-provider/hook-executor.ts

// src/events/events.ts
import { ServerProviderEvents } from "@openfeature/core";
// src/provider/multi-provider/status-tracker.ts
var StatusTracker = class {
constructor(events) {
this.events = events;
this.providerStatuses = {};
}
wrapEventHandler(providerEntry) {
var _a, _b, _c, _d;
const provider = providerEntry.provider;
(_a = provider.events) == null ? void 0 : _a.addHandler(ServerProviderEvents.Error, (details) => {
this.changeProviderStatus(providerEntry.name, ServerProviderStatus.ERROR, details);
});
(_b = provider.events) == null ? void 0 : _b.addHandler(ServerProviderEvents.Stale, (details) => {
this.changeProviderStatus(providerEntry.name, ServerProviderStatus.STALE, details);
});
(_c = provider.events) == null ? void 0 : _c.addHandler(ServerProviderEvents.ConfigurationChanged, (details) => {
this.events.emit(ServerProviderEvents.ConfigurationChanged, details);
});
(_d = provider.events) == null ? void 0 : _d.addHandler(ServerProviderEvents.Ready, (details) => {
this.changeProviderStatus(providerEntry.name, ServerProviderStatus.READY, details);
});
}
providerStatus(name) {
return this.providerStatuses[name];
}
getStatusFromProviderStatuses() {
const statuses = Object.values(this.providerStatuses);
if (statuses.includes(ServerProviderStatus.FATAL)) {
return ServerProviderStatus.FATAL;
} else if (statuses.includes(ServerProviderStatus.NOT_READY)) {
return ServerProviderStatus.NOT_READY;
} else if (statuses.includes(ServerProviderStatus.ERROR)) {
return ServerProviderStatus.ERROR;
} else if (statuses.includes(ServerProviderStatus.STALE)) {
return ServerProviderStatus.STALE;
}
return ServerProviderStatus.READY;
}
changeProviderStatus(name, status, details) {
const currentStatus = this.getStatusFromProviderStatuses();
this.providerStatuses[name] = status;
const newStatus = this.getStatusFromProviderStatuses();
if (currentStatus !== newStatus) {
if (newStatus === ServerProviderStatus.FATAL || newStatus === ServerProviderStatus.ERROR) {
this.events.emit(ServerProviderEvents.Error, details);
} else if (newStatus === ServerProviderStatus.STALE) {
this.events.emit(ServerProviderEvents.Stale, details);
} else if (newStatus === ServerProviderStatus.READY) {
this.events.emit(ServerProviderEvents.Ready, details);
}
}
}
};
// src/provider/multi-provider/strategies/base-evaluation-strategy.ts
var BaseEvaluationStrategy = class {
constructor() {
this.runMode = "sequential";
}
shouldEvaluateThisProvider(strategyContext, _evalContext) {
if (strategyContext.providerStatus === ServerProviderStatus.NOT_READY || strategyContext.providerStatus === ServerProviderStatus.FATAL) {
return false;
}
return true;
}
shouldEvaluateNextProvider(_strategyContext, _context, _result) {
return true;
}
shouldTrackWithThisProvider(strategyContext, _context, _trackingEventName, _trackingEventDetails) {
if (strategyContext.providerStatus === ServerProviderStatus.NOT_READY || strategyContext.providerStatus === ServerProviderStatus.FATAL) {
return false;
}
return true;
}
hasError(resolution) {
return "thrownError" in resolution || !!resolution.details.errorCode;
}
hasErrorWithCode(resolution, code) {
var _a;
return "thrownError" in resolution ? ((_a = resolution.thrownError) == null ? void 0 : _a.code) === code : resolution.details.errorCode === code;
}
collectProviderErrors(resolutions) {
var _a;
const errors = [];
for (const resolution of resolutions) {
if ("thrownError" in resolution) {
errors.push({ providerName: resolution.providerName, error: resolution.thrownError });
} else if (resolution.details.errorCode) {
errors.push({
providerName: resolution.providerName,
error: new ErrorWithCode(resolution.details.errorCode, (_a = resolution.details.errorMessage) != null ? _a : "unknown error")
});
}
}
return { errors };
}
resolutionToFinalResult(resolution) {
return { details: resolution.details, provider: resolution.provider, providerName: resolution.providerName };
}
};
// src/provider/multi-provider/strategies/first-match-strategy.ts
import { ErrorCode as ErrorCode2 } from "@openfeature/core";
var FirstMatchStrategy = class extends BaseEvaluationStrategy {
shouldEvaluateNextProvider(strategyContext, context, result) {
if (this.hasErrorWithCode(result, ErrorCode2.FLAG_NOT_FOUND)) {
return true;
}
if (this.hasError(result)) {
return false;
}
return false;
}
determineFinalResult(strategyContext, context, resolutions) {
const finalResolution = resolutions[resolutions.length - 1];
if (this.hasError(finalResolution)) {
return this.collectProviderErrors(resolutions);
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/strategies/first-successful-strategy.ts
var FirstSuccessfulStrategy = class extends BaseEvaluationStrategy {
shouldEvaluateNextProvider(strategyContext, context, result) {
return this.hasError(result);
}
determineFinalResult(strategyContext, context, resolutions) {
const finalResolution = resolutions[resolutions.length - 1];
if (this.hasError(finalResolution)) {
return this.collectProviderErrors(resolutions);
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/strategies/comparison-strategy.ts
import { GeneralError as GeneralError3 } from "@openfeature/core";
var ComparisonStrategy = class extends BaseEvaluationStrategy {
constructor(fallbackProvider, onMismatch) {
super();
this.fallbackProvider = fallbackProvider;
this.onMismatch = onMismatch;
this.runMode = "parallel";
}
determineFinalResult(strategyContext, context, resolutions) {
var _a;
let value;
let fallbackResolution;
let finalResolution;
let mismatch = false;
for (const [i, resolution] of resolutions.entries()) {
if (this.hasError(resolution)) {
return this.collectProviderErrors(resolutions);
}
if (resolution.provider === this.fallbackProvider) {
fallbackResolution = resolution;
}
if (i === 0) {
finalResolution = resolution;
}
if (typeof value !== "undefined" && value !== resolution.details.value) {
mismatch = true;
} else {
value = resolution.details.value;
}
}
if (!fallbackResolution) {
throw new GeneralError3("Fallback provider not found in resolution results");
}
if (!finalResolution) {
throw new GeneralError3("Final resolution not found in resolution results");
}
if (mismatch) {
(_a = this.onMismatch) == null ? void 0 : _a.call(this, resolutions);
return {
details: fallbackResolution.details,
provider: fallbackResolution.provider
};
}
return this.resolutionToFinalResult(finalResolution);
}
};
// src/provider/multi-provider/multi-provider.ts

@@ -485,3 +294,3 @@ var MultiProvider = class _MultiProvider {

this.providerEntriesByName = {};
this.statusTracker = new StatusTracker(this.events);
this.statusTracker = new StatusTracker(this.events, ServerProviderStatus, ServerProviderEvents);
this.hookExecutor = new HookExecutor(this.logger);

@@ -558,3 +367,3 @@ this.registerProviders(constructorProviders);

if (!hookContext || !hookHints) {
throw new GeneralError4("Hook context not available for evaluation");
throw new GeneralError2("Hook context not available for evaluation");
}

@@ -587,3 +396,3 @@ const tasks = [];

if (!finalResult.details) {
throw new GeneralError4("No result was returned from any provider");
throw new GeneralError2("No result was returned from any provider");
}

@@ -667,3 +476,3 @@ return finalResult.details;

default:
throw new GeneralError4("Invalid flag evaluation type");
throw new GeneralError2("Invalid flag evaluation type");
}

@@ -713,3 +522,3 @@ });

const errorMessage = err == null ? void 0 : err.message;
const errorCode = (err == null ? void 0 : err.code) || ErrorCode3.GENERAL;
const errorCode = (err == null ? void 0 : err.code) || ErrorCode2.GENERAL;
return {

@@ -727,12 +536,7 @@ errorCode,

// src/open-feature.ts
import {
OpenFeatureCommonAPI,
ProviderWrapper,
objectOrUndefined,
stringOrUndefined
} from "@openfeature/core";
import { OpenFeatureCommonAPI, ProviderWrapper, objectOrUndefined, stringOrUndefined } from "@openfeature/core";
// src/client/internal/open-feature-client.ts
import {
ErrorCode as ErrorCode4,
ErrorCode as ErrorCode3,
ProviderFatalError,

@@ -949,5 +753,3 @@ ProviderNotReadyError,

Object.assign(accumulatedContext, hookResult);
for (let i = 0; i < hooks.length; i++) {
Object.assign(hookContexts[hookContextIndex].context, accumulatedContext);
}
Object.assign(hookContext.context, accumulatedContext);
}

@@ -1022,3 +824,3 @@ }

const errorMessage = err == null ? void 0 : err.message;
const errorCode = (err == null ? void 0 : err.code) || ErrorCode4.GENERAL;
const errorCode = (err == null ? void 0 : err.code) || ErrorCode3.GENERAL;
return {

@@ -1179,7 +981,4 @@ errorCode,

export {
AggregateError,
AsyncLocalStorageTransactionContextPropagator,
BaseEvaluationStrategy,
ComparisonStrategy,
ErrorWithCode,
FirstMatchStrategy,

@@ -1195,6 +994,4 @@ FirstSuccessfulStrategy,

ServerProviderEvents as ProviderEvents,
ServerProviderStatus as ProviderStatus,
constructAggregateError,
throwAggregateErrorFromPromiseResults
ServerProviderStatus as ProviderStatus
};
//# sourceMappingURL=index.js.map
+44
-117

@@ -1,4 +0,4 @@

import { BaseHook, FlagValue, EvaluationContext, HookHints, EvaluationDetails, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, FlagValueType, TrackingEventDetails, ErrorCode, ProviderMetadata, OpenFeatureError, GeneralError, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core';
import { BaseHook, FlagValue, EvaluationContext, HookHints, EvaluationDetails, JsonValue, CommonProvider, ServerProviderStatus, Logger, ResolutionDetails, GenericEventEmitter, ServerProviderEvents, ProviderEntryInput, ProviderMetadata, RegisteredProvider, BaseEvaluationStrategy, TrackingEventDetails, BaseStrategyProviderContext, BaseStrategyPerProviderContext, BaseProviderResolutionResult, BaseProviderResolutionSuccessResult, BaseProviderResolutionErrorResult, BaseFinalResult, BaseFirstMatchStrategy, BaseFirstSuccessfulStrategy, BaseComparisonStrategy, EvaluationLifeCycle, ManageContext, ManageLogger, Eventing, ClientMetadata, OpenFeatureCommonAPI, ProviderWrapper } from '@openfeature/core';
export * from '@openfeature/core';
export { ServerProviderEvents as ProviderEvents, ServerProviderStatus as ProviderStatus } from '@openfeature/core';
export { ServerProviderEvents as ProviderEvents, ServerProviderStatus as ProviderStatus, StrategyEvaluationContext } from '@openfeature/core';
import { EventEmitter } from 'node:events';

@@ -216,97 +216,4 @@

type StrategyEvaluationContext = {
flagKey: string;
flagType: FlagValueType;
};
type StrategyProviderContext = {
provider: Provider;
providerName: string;
providerStatus: ServerProviderStatus;
};
type StrategyPerProviderContext = StrategyEvaluationContext & StrategyProviderContext;
type ProviderResolutionResultBase = {
provider: Provider;
providerName: string;
};
type ProviderResolutionSuccessResult<T extends FlagValue> = ProviderResolutionResultBase & {
details: ResolutionDetails<T>;
};
type ProviderResolutionErrorResult = ProviderResolutionResultBase & {
thrownError: unknown;
};
type ProviderResolutionResult<T extends FlagValue> = ProviderResolutionSuccessResult<T> | ProviderResolutionErrorResult;
type FinalResult<T extends FlagValue> = {
details?: ResolutionDetails<T>;
provider?: Provider;
providerName?: string;
errors?: {
providerName: string;
error: unknown;
}[];
};
/**
* Base strategy to inherit from. Not directly usable, as strategies must implement the "determineResult" method
* Contains default implementations for `shouldEvaluateThisProvider` and `shouldEvaluateNextProvider`
*/
declare abstract class BaseEvaluationStrategy {
runMode: 'parallel' | 'sequential';
shouldEvaluateThisProvider(strategyContext: StrategyPerProviderContext, _evalContext?: EvaluationContext): boolean;
shouldEvaluateNextProvider<T extends FlagValue>(_strategyContext?: StrategyPerProviderContext, _context?: EvaluationContext, _result?: ProviderResolutionResult<T>): boolean;
shouldTrackWithThisProvider(strategyContext: StrategyProviderContext, _context?: EvaluationContext, _trackingEventName?: string, _trackingEventDetails?: TrackingEventDetails): boolean;
abstract determineFinalResult<T extends FlagValue>(strategyContext: StrategyEvaluationContext, context: EvaluationContext, resolutions: ProviderResolutionResult<T>[]): FinalResult<T>;
protected hasError(resolution: ProviderResolutionResult<FlagValue>): resolution is ProviderResolutionErrorResult | (ProviderResolutionSuccessResult<FlagValue> & {
details: ResolutionDetails<FlagValue> & {
errorCode: ErrorCode;
};
});
protected hasErrorWithCode(resolution: ProviderResolutionResult<FlagValue>, code: ErrorCode): boolean;
protected collectProviderErrors<T extends FlagValue>(resolutions: ProviderResolutionResult<T>[]): FinalResult<T>;
protected resolutionToFinalResult<T extends FlagValue>(resolution: ProviderResolutionSuccessResult<T>): {
details: ResolutionDetails<T>;
provider: Provider;
providerName: string;
};
}
/**
* Return the first result that did not indicate "flag not found".
* If any provider in the course of evaluation returns or throws an error, throw that error
*/
declare class FirstMatchStrategy extends BaseEvaluationStrategy {
shouldEvaluateNextProvider<T extends FlagValue>(strategyContext: StrategyPerProviderContext, context: EvaluationContext, result: ProviderResolutionResult<T>): boolean;
determineFinalResult<T extends FlagValue>(strategyContext: StrategyPerProviderContext, context: EvaluationContext, resolutions: ProviderResolutionResult<T>[]): FinalResult<T>;
}
/**
* Return the first result that did NOT result in an error
* If any provider in the course of evaluation returns or throws an error, ignore it as long as there is a successful result
* If there is no successful result, throw all errors
*/
declare class FirstSuccessfulStrategy extends BaseEvaluationStrategy {
shouldEvaluateNextProvider<T extends FlagValue>(strategyContext: StrategyPerProviderContext, context: EvaluationContext, result: ProviderResolutionResult<T>): boolean;
determineFinalResult<T extends FlagValue>(strategyContext: StrategyPerProviderContext, context: EvaluationContext, resolutions: ProviderResolutionResult<T>[]): FinalResult<T>;
}
/**
* Evaluate all providers in parallel and compare the results.
* If the values agree, return the value
* If the values disagree, return the value from the configured "fallback provider" and execute the "onMismatch"
* callback if defined
*/
declare class ComparisonStrategy extends BaseEvaluationStrategy {
private fallbackProvider;
private onMismatch?;
runMode: "parallel";
constructor(fallbackProvider: Provider, onMismatch?: ((resolutions: ProviderResolutionResult<FlagValue>[]) => void) | undefined);
determineFinalResult<T extends FlagValue>(strategyContext: StrategyPerProviderContext, context: EvaluationContext, resolutions: ProviderResolutionResult<T>[]): FinalResult<T>;
}
type ProviderEntryInput = {
provider: Provider;
name?: string;
};
type RegisteredProvider = Required<ProviderEntryInput>;
declare class MultiProvider implements Provider {
readonly constructorProviders: ProviderEntryInput[];
readonly constructorProviders: ProviderEntryInput<Provider>[];
private readonly evaluationStrategy;

@@ -319,7 +226,7 @@ private readonly logger;

metadata: ProviderMetadata;
providerEntries: RegisteredProvider[];
providerEntries: RegisteredProvider<Provider>[];
private providerEntriesByName;
private hookExecutor;
private statusTracker;
constructor(constructorProviders: ProviderEntryInput[], evaluationStrategy?: BaseEvaluationStrategy, logger?: Logger);
constructor(constructorProviders: ProviderEntryInput<Provider>[], evaluationStrategy?: BaseEvaluationStrategy<ServerProviderStatus, Provider>, logger?: Logger);
private registerProviders;

@@ -341,21 +248,41 @@ initialize(context?: EvaluationContext): Promise<void>;

declare class ErrorWithCode extends OpenFeatureError {
code: ErrorCode;
constructor(code: ErrorCode, message: string);
/**
* Pre-configured strategy exports for the server SDK.
* These classes extend the base strategies from @openfeature/core with the
* server-specific ProviderStatus enum already bound.
*/
/**
* Pre-bound type aliases for server SDK.
* These types have the server-specific ProviderStatus and Provider types already applied,
* providing backward compatibility for existing consumers.
*/
type StrategyProviderContext = BaseStrategyProviderContext<ServerProviderStatus, Provider>;
type StrategyPerProviderContext = BaseStrategyPerProviderContext<ServerProviderStatus, Provider>;
type ProviderResolutionResult<T extends FlagValue> = BaseProviderResolutionResult<T, ServerProviderStatus, Provider>;
type ProviderResolutionSuccessResult<T extends FlagValue> = BaseProviderResolutionSuccessResult<T, ServerProviderStatus, Provider>;
type ProviderResolutionErrorResult = BaseProviderResolutionErrorResult<ServerProviderStatus, Provider>;
type FinalResult<T extends FlagValue> = BaseFinalResult<T, ServerProviderStatus, Provider>;
/**
* Evaluates providers in order and returns the first successful result.
* Providers that return FLAG_NOT_FOUND are skipped. Any other error stops evaluation.
*/
declare class FirstMatchStrategy extends BaseFirstMatchStrategy<ServerProviderStatus, Provider> {
constructor();
}
declare class AggregateError extends GeneralError {
originalErrors: {
source: string;
error: unknown;
}[];
constructor(message: string, originalErrors: {
source: string;
error: unknown;
}[]);
/**
* Evaluates providers in order and returns the first successful result.
* Any error causes that provider to be skipped.
*/
declare class FirstSuccessfulStrategy extends BaseFirstSuccessfulStrategy<ServerProviderStatus, Provider> {
constructor();
}
declare const constructAggregateError: (providerErrors: {
error: unknown;
providerName: string;
}[]) => AggregateError;
declare const throwAggregateErrorFromPromiseResults: (result: PromiseSettledResult<unknown>[], providerEntries: RegisteredProvider[]) => void;
/**
* Evaluates all providers in parallel and compares results.
* If all providers agree, returns that result. Otherwise, returns the fallback provider's result.
*/
declare class ComparisonStrategy extends BaseComparisonStrategy<ServerProviderStatus, Provider> {
constructor(fallbackProvider: Provider, onMismatch?: (resolutions: ProviderResolutionResult<FlagValue>[]) => void);
}

@@ -566,3 +493,3 @@ interface Tracking {

export { AggregateError, AsyncLocalStorageTransactionContextPropagator, BaseEvaluationStrategy, ComparisonStrategy, ErrorWithCode, FirstMatchStrategy, FirstSuccessfulStrategy, InMemoryProvider, MultiProvider, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter, constructAggregateError, throwAggregateErrorFromPromiseResults };
export type { Client, Features, FinalResult, FlagEvaluationOptions, Hook, ManageTransactionContextPropagator, Provider, ProviderResolutionErrorResult, ProviderResolutionResult, ProviderResolutionSuccessResult, StrategyEvaluationContext, StrategyPerProviderContext, StrategyProviderContext, Tracking, TransactionContext, TransactionContextPropagator };
export { AsyncLocalStorageTransactionContextPropagator, ComparisonStrategy, FirstMatchStrategy, FirstSuccessfulStrategy, InMemoryProvider, MultiProvider, NOOP_PROVIDER, NOOP_TRANSACTION_CONTEXT_PROPAGATOR, OpenFeature, OpenFeatureAPI, OpenFeatureEventEmitter };
export type { Client, Features, FinalResult, FlagEvaluationOptions, Hook, ManageTransactionContextPropagator, Provider, ProviderResolutionErrorResult, ProviderResolutionResult, ProviderResolutionSuccessResult, StrategyPerProviderContext, StrategyProviderContext, Tracking, TransactionContext, TransactionContextPropagator };
{
"name": "@openfeature/server-sdk",
"version": "1.20.1",
"version": "1.20.2",
"description": "OpenFeature SDK for JavaScript",

@@ -51,7 +51,7 @@ "main": "./dist/cjs/index.js",

"peerDependencies": {
"@openfeature/core": "^1.9.0"
"@openfeature/core": "^1.9.2"
},
"devDependencies": {
"@openfeature/core": "^1.9.0"
"@openfeature/core": "^1.9.2"
}
}
+63
-49

@@ -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.20.1">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.20.1&color=blue&style=for-the-badge" />
<a href="https://github.com/open-feature/js-sdk/releases/tag/server-sdk-v1.20.2">
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v1.20.2&color=blue&style=for-the-badge" />
</a>

@@ -92,3 +92,3 @@ <!-- x-release-please-end -->

if (v2Enabled) {
console.log("v2 is enabled");
console.log('v2 is enabled');
}

@@ -103,15 +103,15 @@ ```

| Status | Features | Description |
| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
| ✅ | [Logging](#logging) | Integrate with popular logging packages. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
| ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. |
| Status | Features | Description |
| ------ | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| ✅ | [Providers](#providers) | Integrate with a commercial, open source, or in-house feature management tool. |
| ✅ | [Targeting](#targeting) | Contextually-aware flag evaluation using [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context). |
| ✅ | [Hooks](#hooks) | Add functionality to various stages of the flag evaluation life-cycle. |
| ✅ | [Logging](#logging) | Integrate with popular logging packages. |
| ✅ | [Domains](#domains) | Logically bind clients with providers. |
| ✅ | [Eventing](#eventing) | React to state changes in the provider or flag management system. |
| ✅ | [Transaction Context Propagation](#transaction-context-propagation) | Set a specific [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) for a transaction (e.g. an HTTP request or a thread) |
| ✅ | [Tracking](#tracking) | Associate user actions with feature flag evaluations, particularly for A/B testing. |
| ✅ | [Shutdown](#shutdown) | Gracefully clean up a provider during application shutdown. |
| ✅ | [Extending](#extending) | Extend OpenFeature with custom providers and hooks. |
| ✅ | [Multi-Provider](#multi-provider) | Combine multiple providers with configurable evaluation strategies. |

@@ -168,6 +168,3 @@ <sub>Implemented: ✅ | In-progress: ⚠️ | Not implemented yet: ❌</sub>

// Create multi-provider with a strategy
const multiProvider = new MultiProvider(
[primaryProvider, backupProvider],
new FirstMatchStrategy()
);
const multiProvider = new MultiProvider([primaryProvider, backupProvider], new FirstMatchStrategy());

@@ -198,3 +195,3 @@ // Register the multi-provider

[newProvider, oldProvider], // New provider is consulted first
new FirstMatchStrategy()
new FirstMatchStrategy(),
);

@@ -215,9 +212,6 @@

const multiProvider = new MultiProvider(
[
{ provider: providerA },
{ provider: providerB }
],
[{ provider: providerA }, { provider: providerB }],
new ComparisonStrategy(providerA, (resolutions) => {
console.warn('Mismatch detected', resolutions);
})
}),
);

@@ -236,3 +230,3 @@

// set a value to the global context
OpenFeature.setContext({ region: "us-east-1" });
OpenFeature.setContext({ region: 'us-east-1' });

@@ -247,3 +241,3 @@ // set a value to the client context

email: req.session.email,
product: req.productId
product: req.productId,
};

@@ -266,3 +260,3 @@

```ts
import { OpenFeature } from "@openfeature/server-sdk";
import { OpenFeature } from '@openfeature/server-sdk';

@@ -277,3 +271,3 @@ // add a hook globally, to run on all evaluations

// add a hook for this evaluation only
const boolValue = await client.getBooleanValue("bool-flag", false, { hooks: [new ExampleHook()]});
const boolValue = await client.getBooleanValue('bool-flag', false, { hooks: [new ExampleHook()] });
```

@@ -288,3 +282,3 @@

```ts
import type { Logger } from "@openfeature/server-sdk";
import type { Logger } from '@openfeature/server-sdk';

@@ -309,13 +303,13 @@ // The logger can be anything that conforms with the Logger interface

```ts
import { OpenFeature, InMemoryProvider } from "@openfeature/server-sdk";
import { OpenFeature, InMemoryProvider } from '@openfeature/server-sdk';
const myFlags = {
'v2_enabled': {
v2_enabled: {
variants: {
on: true,
off: false
off: false,
},
disabled: false,
defaultVariant: "on"
}
defaultVariant: 'on',
},
};

@@ -326,3 +320,3 @@

// Registering a provider to a domain
OpenFeature.setProvider("my-domain", new InMemoryProvider(someOtherFlags));
OpenFeature.setProvider('my-domain', new InMemoryProvider(someOtherFlags));

@@ -332,3 +326,3 @@ // A Client bound to the default provider

// A Client bound to the InMemoryProvider provider
const domainScopedClient = OpenFeature.getClient("my-domain");
const domainScopedClient = OpenFeature.getClient('my-domain');
```

@@ -370,6 +364,6 @@

```ts
import express, { Request, Response, NextFunction } from "express";
import express, { Request, Response, NextFunction } from 'express';
import { OpenFeature, AsyncLocalStorageTransactionContextPropagator } from '@openfeature/server-sdk';
OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator())
OpenFeature.setTransactionContextPropagator(new AsyncLocalStorageTransactionContextPropagator());

@@ -381,3 +375,3 @@ /**

app.use((req: Request, res: Response, next: NextFunction) => {
const ip = res.headers.get("X-Forwarded-For")
const ip = res.headers.get('X-Forwarded-For');
OpenFeature.setTransactionContext({ targetingKey: req.user.id, ipAddress: ip }, () => {

@@ -387,3 +381,3 @@ // The transaction context is used in any flag evaluation throughout the whole call chain of next

});
})
});
```

@@ -414,3 +408,3 @@

await OpenFeature.close()
await OpenFeature.close();
```

@@ -435,3 +429,3 @@

ProviderEventEmitter,
ResolutionDetails
ResolutionDetails,
} from '@openfeature/server-sdk';

@@ -448,12 +442,32 @@

hooks?: Hook[];
resolveBooleanEvaluation(flagKey: string, defaultValue: boolean, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<boolean>> {
resolveBooleanEvaluation(
flagKey: string,
defaultValue: boolean,
context: EvaluationContext,
logger: Logger,
): Promise<ResolutionDetails<boolean>> {
// code to evaluate a boolean
}
resolveStringEvaluation(flagKey: string, defaultValue: string, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<string>> {
resolveStringEvaluation(
flagKey: string,
defaultValue: string,
context: EvaluationContext,
logger: Logger,
): Promise<ResolutionDetails<string>> {
// code to evaluate a string
}
resolveNumberEvaluation(flagKey: string, defaultValue: number, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<number>> {
resolveNumberEvaluation(
flagKey: string,
defaultValue: number,
context: EvaluationContext,
logger: Logger,
): Promise<ResolutionDetails<number>> {
// code to evaluate a number
}
resolveObjectEvaluation<T extends JsonValue>(flagKey: string, defaultValue: T, context: EvaluationContext, logger: Logger): Promise<ResolutionDetails<T>> {
resolveObjectEvaluation<T extends JsonValue>(
flagKey: string,
defaultValue: T,
context: EvaluationContext,
logger: Logger,
): Promise<ResolutionDetails<T>> {
// code to evaluate an object

@@ -483,3 +497,3 @@ }

```ts
import type { Hook, HookContext, EvaluationDetails, FlagValue } from "@openfeature/server-sdk";
import type { Hook, HookContext, EvaluationDetails, FlagValue } from '@openfeature/server-sdk';

@@ -486,0 +500,0 @@ export class MyHook implements Hook {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display