Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@eppo/js-client-sdk-common

Package Overview
Dependencies
Maintainers
8
Versions
86
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@eppo/js-client-sdk-common - npm Package Compare versions

Comparing version 4.0.0 to 4.0.1

1

dist/client/eppo-client.d.ts

@@ -161,2 +161,3 @@ import { IAssignmentLogger } from '../assignment-logger';

getBanditActionDetails(flagKey: string, subjectKey: string, subjectAttributes: BanditSubjectAttributes, actions: BanditActions, defaultValue: string): IAssignmentDetails<string>;
private evaluateBanditAction;
private ensureNonContextualSubjectAttributes;

@@ -163,0 +164,0 @@ private ensureContextualSubjectAttributes;

94

dist/client/eppo-client.js

@@ -257,64 +257,74 @@ "use strict";

getBanditActionDetails(flagKey, subjectKey, subjectAttributes, actions, defaultValue) {
var _a, _b, _c;
const flagEvaluationDetailsBuilder = this.flagEvaluationDetailsBuilder(flagKey);
const defaultResult = { variation: defaultValue, action: null };
var _a, _b;
let variation = defaultValue;
let action = null;
// Initialize with a generic evaluation details. This will mutate as the function progresses.
let evaluationDetails = this.flagEvaluationDetailsBuilder(flagKey).buildForNoneResult('ASSIGNMENT_ERROR', 'Unexpected error getting assigned variation for bandit action');
try {
const banditVariations = (_a = this.banditVariationConfigurationStore) === null || _a === void 0 ? void 0 : _a.get(flagKey);
if (banditVariations && !Object.keys(actions).length) {
// No actions passed for a flag known to have an active bandit, so we just return the default values so that
// we don't log a variation or bandit assignment
return Object.assign(Object.assign({}, defaultResult), { evaluationDetails: flagEvaluationDetailsBuilder.buildForNoneResult('NO_ACTIONS_SUPPLIED_FOR_BANDIT', 'No bandit actions passed for a flag known to have an active bandit') });
}
// Get the assigned variation for the flag with a possible bandit
// Note for getting assignments, we don't care about context
const nonContextualSubjectAttributes = this.ensureNonContextualSubjectAttributes(subjectAttributes);
const { variation: _variation, evaluationDetails } = this.getStringAssignmentDetails(flagKey, subjectKey, nonContextualSubjectAttributes, defaultValue);
variation = _variation;
const { variation: assignedVariation, evaluationDetails: assignmentEvaluationDetails } = this.getStringAssignmentDetails(flagKey, subjectKey, nonContextualSubjectAttributes, defaultValue);
variation = assignedVariation;
evaluationDetails = assignmentEvaluationDetails;
// Check if the assigned variation is an active bandit
// Note: the reason for non-bandit assignments include the subject being bucketed into a non-bandit variation or
// a rollout having been done.
const banditVariations = (_a = this.banditVariationConfigurationStore) === null || _a === void 0 ? void 0 : _a.get(flagKey);
const banditKey = (_b = banditVariations === null || banditVariations === void 0 ? void 0 : banditVariations.find((banditVariation) => banditVariation.variationValue === variation)) === null || _b === void 0 ? void 0 : _b.key;
if (banditKey) {
// Retrieve the model parameters for the bandit
const banditParameters = (_c = this.banditModelConfigurationStore) === null || _c === void 0 ? void 0 : _c.get(banditKey);
if (!banditParameters) {
throw new Error('No model parameters for bandit ' + banditKey);
}
const banditModelData = banditParameters.modelData;
const contextualSubjectAttributes = this.ensureContextualSubjectAttributes(subjectAttributes);
const actionsWithContextualAttributes = this.ensureActionsWithContextualAttributes(actions);
const banditEvaluation = this.banditEvaluator.evaluateBandit(flagKey, subjectKey, contextualSubjectAttributes, actionsWithContextualAttributes, banditModelData);
action = banditEvaluation.actionKey;
evaluationDetails.banditKey = banditKey;
action = this.evaluateBanditAction(flagKey, subjectKey, subjectAttributes, actions, banditKey, evaluationDetails);
evaluationDetails.banditAction = action;
evaluationDetails.banditKey = banditKey;
const banditEvent = {
timestamp: new Date().toISOString(),
featureFlag: flagKey,
bandit: banditKey,
subject: subjectKey,
action,
actionProbability: banditEvaluation.actionWeight,
optimalityGap: banditEvaluation.optimalityGap,
modelVersion: banditParameters.modelVersion,
subjectNumericAttributes: contextualSubjectAttributes.numericAttributes,
subjectCategoricalAttributes: contextualSubjectAttributes.categoricalAttributes,
actionNumericAttributes: actionsWithContextualAttributes[action].numericAttributes,
actionCategoricalAttributes: actionsWithContextualAttributes[action].categoricalAttributes,
metaData: this.buildLoggerMetadata(),
evaluationDetails,
};
this.logBanditAction(banditEvent);
}
return { variation, action, evaluationDetails };
}
catch (err) {
application_logger_1.logger.error('Error evaluating bandit action', err);
application_logger_1.logger.error('Error determining bandit action', err);
if (!this.isGracefulFailureMode) {
throw err;
}
return Object.assign(Object.assign({}, defaultResult), { evaluationDetails: flagEvaluationDetailsBuilder.buildForNoneResult('ASSIGNMENT_ERROR', `Error evaluating bandit action: ${err.message}`) });
if (variation) {
// If we have a variation, the assignment succeeded and the error was with the bandit part.
// Update the flag evaluation code to indicate that
evaluationDetails.flagEvaluationCode = 'BANDIT_ERROR';
}
evaluationDetails.flagEvaluationDescription = `Error evaluating bandit action: ${err.message}`;
}
return { variation, action, evaluationDetails };
}
evaluateBanditAction(flagKey, subjectKey, subjectAttributes, actions, banditKey, evaluationDetails) {
var _a;
// If no actions, there is nothing to do
if (!Object.keys(actions).length) {
return null;
}
// Retrieve the model parameters for the bandit
const banditParameters = (_a = this.banditModelConfigurationStore) === null || _a === void 0 ? void 0 : _a.get(banditKey);
if (!banditParameters) {
throw new Error('No model parameters for bandit ' + banditKey);
}
const banditModelData = banditParameters.modelData;
const contextualSubjectAttributes = this.ensureContextualSubjectAttributes(subjectAttributes);
const actionsWithContextualAttributes = this.ensureActionsWithContextualAttributes(actions);
const banditEvaluation = this.banditEvaluator.evaluateBandit(flagKey, subjectKey, contextualSubjectAttributes, actionsWithContextualAttributes, banditModelData);
const action = banditEvaluation.actionKey;
const banditEvent = {
timestamp: new Date().toISOString(),
featureFlag: flagKey,
bandit: banditKey,
subject: subjectKey,
action,
actionProbability: banditEvaluation.actionWeight,
optimalityGap: banditEvaluation.optimalityGap,
modelVersion: banditParameters.modelVersion,
subjectNumericAttributes: contextualSubjectAttributes.numericAttributes,
subjectCategoricalAttributes: contextualSubjectAttributes.categoricalAttributes,
actionNumericAttributes: actionsWithContextualAttributes[action].numericAttributes,
actionCategoricalAttributes: actionsWithContextualAttributes[action].categoricalAttributes,
metaData: this.buildLoggerMetadata(),
evaluationDetails,
};
this.logBanditAction(banditEvent);
return action;
}
ensureNonContextualSubjectAttributes(subjectAttributes) {

@@ -321,0 +331,0 @@ let result;

import { Allocation, Variation, VariationType } from './interfaces';
import { Rule } from './rules';
export declare const flagEvaluationCodes: readonly ["MATCH", "FLAG_UNRECOGNIZED_OR_DISABLED", "TYPE_MISMATCH", "ASSIGNMENT_ERROR", "DEFAULT_ALLOCATION_NULL", "NO_ACTIONS_SUPPLIED_FOR_BANDIT"];
export declare const flagEvaluationCodes: readonly ["MATCH", "FLAG_UNRECOGNIZED_OR_DISABLED", "TYPE_MISMATCH", "ASSIGNMENT_ERROR", "DEFAULT_ALLOCATION_NULL", "NO_ACTIONS_SUPPLIED_FOR_BANDIT", "BANDIT_ERROR"];
export declare type FlagEvaluationCode = typeof flagEvaluationCodes[number];

@@ -5,0 +5,0 @@ export declare enum AllocationEvaluationCode {

@@ -12,2 +12,3 @@ "use strict";

'NO_ACTIONS_SUPPLIED_FOR_BANDIT',
'BANDIT_ERROR',
];

@@ -14,0 +15,0 @@ var AllocationEvaluationCode;

{
"name": "@eppo/js-client-sdk-common",
"version": "4.0.0",
"version": "4.0.1",
"description": "Eppo SDK for client-side JavaScript applications (base for both web and react native)",

@@ -5,0 +5,0 @@ "main": "dist/index.js",

@@ -465,20 +465,13 @@ import ApiEndpoints from '../api-endpoints';

): IAssignmentDetails<string> {
const flagEvaluationDetailsBuilder = this.flagEvaluationDetailsBuilder(flagKey);
const defaultResult = { variation: defaultValue, action: null };
let variation = defaultValue;
let action: string | null = null;
// Initialize with a generic evaluation details. This will mutate as the function progresses.
let evaluationDetails: IFlagEvaluationDetails = this.flagEvaluationDetailsBuilder(
flagKey,
).buildForNoneResult(
'ASSIGNMENT_ERROR',
'Unexpected error getting assigned variation for bandit action',
);
try {
const banditVariations = this.banditVariationConfigurationStore?.get(flagKey);
if (banditVariations && !Object.keys(actions).length) {
// No actions passed for a flag known to have an active bandit, so we just return the default values so that
// we don't log a variation or bandit assignment
return {
...defaultResult,
evaluationDetails: flagEvaluationDetailsBuilder.buildForNoneResult(
'NO_ACTIONS_SUPPLIED_FOR_BANDIT',
'No bandit actions passed for a flag known to have an active bandit',
),
};
}
// Get the assigned variation for the flag with a possible bandit

@@ -488,9 +481,11 @@ // Note for getting assignments, we don't care about context

this.ensureNonContextualSubjectAttributes(subjectAttributes);
const { variation: _variation, evaluationDetails } = this.getStringAssignmentDetails(
flagKey,
subjectKey,
nonContextualSubjectAttributes,
defaultValue,
);
variation = _variation;
const { variation: assignedVariation, evaluationDetails: assignmentEvaluationDetails } =
this.getStringAssignmentDetails(
flagKey,
subjectKey,
nonContextualSubjectAttributes,
defaultValue,
);
variation = assignedVariation;
evaluationDetails = assignmentEvaluationDetails;

@@ -500,2 +495,3 @@ // Check if the assigned variation is an active bandit

// a rollout having been done.
const banditVariations = this.banditVariationConfigurationStore?.get(flagKey);
const banditKey = banditVariations?.find(

@@ -506,59 +502,80 @@ (banditVariation) => banditVariation.variationValue === variation,

if (banditKey) {
// Retrieve the model parameters for the bandit
const banditParameters = this.banditModelConfigurationStore?.get(banditKey);
if (!banditParameters) {
throw new Error('No model parameters for bandit ' + banditKey);
}
const banditModelData = banditParameters.modelData;
const contextualSubjectAttributes =
this.ensureContextualSubjectAttributes(subjectAttributes);
const actionsWithContextualAttributes = this.ensureActionsWithContextualAttributes(actions);
const banditEvaluation = this.banditEvaluator.evaluateBandit(
evaluationDetails.banditKey = banditKey;
action = this.evaluateBanditAction(
flagKey,
subjectKey,
contextualSubjectAttributes,
actionsWithContextualAttributes,
banditModelData,
subjectAttributes,
actions,
banditKey,
evaluationDetails,
);
action = banditEvaluation.actionKey;
evaluationDetails.banditAction = action;
evaluationDetails.banditKey = banditKey;
const banditEvent: IBanditEvent = {
timestamp: new Date().toISOString(),
featureFlag: flagKey,
bandit: banditKey,
subject: subjectKey,
action,
actionProbability: banditEvaluation.actionWeight,
optimalityGap: banditEvaluation.optimalityGap,
modelVersion: banditParameters.modelVersion,
subjectNumericAttributes: contextualSubjectAttributes.numericAttributes,
subjectCategoricalAttributes: contextualSubjectAttributes.categoricalAttributes,
actionNumericAttributes: actionsWithContextualAttributes[action].numericAttributes,
actionCategoricalAttributes:
actionsWithContextualAttributes[action].categoricalAttributes,
metaData: this.buildLoggerMetadata(),
evaluationDetails,
};
this.logBanditAction(banditEvent);
}
return { variation, action, evaluationDetails };
} catch (err) {
logger.error('Error evaluating bandit action', err);
logger.error('Error determining bandit action', err);
if (!this.isGracefulFailureMode) {
throw err;
}
return {
...defaultResult,
evaluationDetails: flagEvaluationDetailsBuilder.buildForNoneResult(
'ASSIGNMENT_ERROR',
`Error evaluating bandit action: ${err.message}`,
),
};
if (variation) {
// If we have a variation, the assignment succeeded and the error was with the bandit part.
// Update the flag evaluation code to indicate that
evaluationDetails.flagEvaluationCode = 'BANDIT_ERROR';
}
evaluationDetails.flagEvaluationDescription = `Error evaluating bandit action: ${err.message}`;
}
return { variation, action, evaluationDetails };
}
private evaluateBanditAction(
flagKey: string,
subjectKey: string,
subjectAttributes: BanditSubjectAttributes,
actions: BanditActions,
banditKey: string,
evaluationDetails: IFlagEvaluationDetails,
): string | null {
// If no actions, there is nothing to do
if (!Object.keys(actions).length) {
return null;
}
// Retrieve the model parameters for the bandit
const banditParameters = this.banditModelConfigurationStore?.get(banditKey);
if (!banditParameters) {
throw new Error('No model parameters for bandit ' + banditKey);
}
const banditModelData = banditParameters.modelData;
const contextualSubjectAttributes = this.ensureContextualSubjectAttributes(subjectAttributes);
const actionsWithContextualAttributes = this.ensureActionsWithContextualAttributes(actions);
const banditEvaluation = this.banditEvaluator.evaluateBandit(
flagKey,
subjectKey,
contextualSubjectAttributes,
actionsWithContextualAttributes,
banditModelData,
);
const action = banditEvaluation.actionKey;
const banditEvent: IBanditEvent = {
timestamp: new Date().toISOString(),
featureFlag: flagKey,
bandit: banditKey,
subject: subjectKey,
action,
actionProbability: banditEvaluation.actionWeight,
optimalityGap: banditEvaluation.optimalityGap,
modelVersion: banditParameters.modelVersion,
subjectNumericAttributes: contextualSubjectAttributes.numericAttributes,
subjectCategoricalAttributes: contextualSubjectAttributes.categoricalAttributes,
actionNumericAttributes: actionsWithContextualAttributes[action].numericAttributes,
actionCategoricalAttributes: actionsWithContextualAttributes[action].categoricalAttributes,
metaData: this.buildLoggerMetadata(),
evaluationDetails,
};
this.logBanditAction(banditEvent);
return action;
}
private ensureNonContextualSubjectAttributes(

@@ -565,0 +582,0 @@ subjectAttributes: BanditSubjectAttributes,

@@ -11,2 +11,3 @@ import { Allocation, Variation, VariationType } from './interfaces';

'NO_ACTIONS_SUPPLIED_FOR_BANDIT',
'BANDIT_ERROR',
] as const;

@@ -13,0 +14,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc