diff --git a/src/client/eppo-client.ts b/src/client/eppo-client.ts index a6ff332..623c3a1 100644 --- a/src/client/eppo-client.ts +++ b/src/client/eppo-client.ts @@ -68,10 +68,10 @@ export type FlagConfigurationRequestParameters = { skipInitialPoll?: boolean; }; -export interface IFlagExperiment { +export interface IContainerExperiment { flagKey: string; - controlVariation: T; - treatmentVariations: Array; + controlVariationEntry: T; + treatmentVariationEntries: Array; } export default class EppoClient { @@ -531,32 +531,49 @@ export default class EppoClient { } /** - * For use with 3rd party CMS tooling, such as the Contentful Eppo plugin + * For use with 3rd party CMS tooling, such as the Contentful Eppo plugin. + * + * CMS plugins that integrate with Eppo will follow a common format for + * creating a feature flag. The flag created by the CMS plugin will have + * variations with values 'control', 'treatment-1', 'treatment-2', etc. + * This function allows users to easily return the CMS container entry + * for the assigned variation. + * + * @param flagExperiment the flag key, control container entry and treatment container entries. + * @param subjectKey an identifier of the experiment subject, for example a user ID. + * @param subjectAttributes optional attributes associated with the subject, for example name and email. + * @returns The container entry associated with the experiment. */ - public getExperimentContainer( - flagExperiment: IFlagExperiment, + public getExperimentContainerEntry( + flagExperiment: IContainerExperiment, subjectKey: string, subjectAttributes: Attributes, ): T { - const { flagKey, controlVariation, treatmentVariations } = flagExperiment; + const { flagKey, controlVariationEntry, treatmentVariationEntries } = flagExperiment; const assignment = this.getStringAssignment(flagKey, subjectKey, subjectAttributes, 'control'); if (assignment === 'control') { - return controlVariation; + return controlVariationEntry; } if (!assignment.startsWith('treatment-')) { logger.warn( `Variation ${assignment} cannot be mapped to a container. Defaulting to control variation.`, ); - return controlVariation; + return controlVariationEntry; + } + const treatmentVariationIndex = Number.parseInt(assignment.split('-')[1]) - 1; + if (isNaN(treatmentVariationIndex)) { + logger.warn( + `Variation ${assignment} cannot be mapped to a container. Defaulting to control variation.`, + ); + return controlVariationEntry; } - const treatmentVariationIndex = Number.parseInt(assignment.split('-')[1]); - if (treatmentVariationIndex > treatmentVariations.length) { + if (treatmentVariationIndex >= treatmentVariationEntries.length) { logger.warn( `Selected treatment variation (${treatmentVariationIndex}) index is out of bounds. Defaulting to control variation.`, ); - return controlVariation; + return controlVariationEntry; } - return treatmentVariations[treatmentVariationIndex - 1]; + return treatmentVariationEntries[treatmentVariationIndex]; } private evaluateBanditAction( diff --git a/src/client/test-utils.ts b/src/client/test-utils.ts index 13a52e3..546ae36 100644 --- a/src/client/test-utils.ts +++ b/src/client/test-utils.ts @@ -12,7 +12,7 @@ export async function initConfiguration( queryParams: { apiKey: 'dummy', sdkName: 'js-client-sdk-common', - sdkVersion: '1.0.0', + sdkVersion: '3.0.0', }, }); const httpClient = new FetchHttpClient(apiEndpoints, 1000); diff --git a/src/index.ts b/src/index.ts index eb79512..a4b0eec 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,6 +18,7 @@ import { import EppoClient, { FlagConfigurationRequestParameters, IAssignmentDetails, + IContainerExperiment, } from './client/eppo-client'; import FlagConfigRequestor from './configuration-requestor'; import { @@ -48,6 +49,7 @@ export { IAssignmentEvent, IBanditLogger, IBanditEvent, + IContainerExperiment, EppoClient, constants, ApiEndpoints,