UNPKG

vwo-fme-node-sdk

Version:

VWO Node/JavaScript SDK for Feature Management and Experimentation

310 lines 14.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setVariationAllocation = setVariationAllocation; exports.assignRangeValues = assignRangeValues; exports.scaleVariationWeights = scaleVariationWeights; exports.getBucketingSeed = getBucketingSeed; exports.getVariationFromCampaignKey = getVariationFromCampaignKey; exports.setCampaignAllocation = setCampaignAllocation; exports.getGroupDetailsIfCampaignPartOfIt = getGroupDetailsIfCampaignPartOfIt; exports.getCampaignsByGroupId = getCampaignsByGroupId; exports.getFeatureKeysFromCampaignIds = getFeatureKeysFromCampaignIds; exports.getCampaignIdsFromFeatureKey = getCampaignIdsFromFeatureKey; exports.assignRangeValuesMEG = assignRangeValuesMEG; /** * Copyright 2024-2025 Wingify Software Pvt. Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var constants_1 = require("../constants"); var CampaignTypeEnum_1 = require("../enums/CampaignTypeEnum"); var log_messages_1 = require("../enums/log-messages"); var VariationModel_1 = require("../models/campaign/VariationModel"); var logger_1 = require("../packages/logger"); var LogMessageUtil_1 = require("./LogMessageUtil"); /** * Sets the variation allocation for a given campaign based on its type. * If the campaign type is ROLLOUT or PERSONALIZE, it handles the campaign using `_handleRolloutCampaign`. * Otherwise, it assigns range values to each variation in the campaign. * @param {CampaignModel} campaign - The campaign for which to set the variation allocation. */ function setVariationAllocation(campaign) { // Check if the campaign type is ROLLOUT or PERSONALIZE if (campaign.getType() === CampaignTypeEnum_1.CampaignTypeEnum.ROLLOUT || campaign.getType() === CampaignTypeEnum_1.CampaignTypeEnum.PERSONALIZE) { _handleRolloutCampaign(campaign); } else { var currentAllocation_1 = 0; // Iterate over each variation in the campaign campaign.getVariations().forEach(function (variation) { // Assign range values to the variation and update the current allocation var stepFactor = assignRangeValues(variation, currentAllocation_1); currentAllocation_1 += stepFactor; // Log the range allocation for debugging logger_1.LogManager.Instance.info((0, LogMessageUtil_1.buildMessage)(log_messages_1.InfoLogMessagesEnum.VARIATION_RANGE_ALLOCATION, { variationKey: variation.getKey(), campaignKey: campaign.getKey(), variationWeight: variation.getWeight(), startRange: variation.getStartRangeVariation(), endRange: variation.getEndRangeVariation(), })); }); } } /** * Assigns start and end range values to a variation based on its weight. * @param {VariationModel} data - The variation model to assign range values. * @param {number} currentAllocation - The current allocation value before this variation. * @returns {number} The step factor calculated from the variation's weight. */ function assignRangeValues(data, currentAllocation) { // Calculate the bucket range based on the variation's weight var stepFactor = _getVariationBucketRange(data.getWeight()); // Set the start and end range of the variation if (stepFactor) { data.setStartRange(currentAllocation + 1); data.setEndRange(currentAllocation + stepFactor); } else { data.setStartRange(-1); data.setEndRange(-1); } return stepFactor; } /** * Scales the weights of variations to sum up to 100%. * @param {any[]} variations - The list of variations to scale. */ function scaleVariationWeights(variations) { // Calculate the total weight of all variations var totalWeight = variations.reduce(function (acc, variation) { return acc + variation.weight; }, 0); // If total weight is zero, assign equal weight to each variation if (!totalWeight) { var equalWeight_1 = 100 / variations.length; variations.forEach(function (variation) { return (variation.weight = equalWeight_1); }); } else { // Scale each variation's weight to make the total 100% variations.forEach(function (variation) { return (variation.weight = (variation.weight / totalWeight) * 100); }); } } /** * Generates a bucketing seed based on user ID, campaign, and optional group ID. * @param {string} userId - The user ID. * @param {any} campaign - The campaign object. * @param {string} [groupId] - The optional group ID. * @returns {string} The bucketing seed. */ function getBucketingSeed(userId, campaign, groupId) { // Return a seed combining group ID and user ID if group ID is provided if (groupId) { return "".concat(groupId, "_").concat(userId); } var isRolloutOrPersonalize = campaign.getType() === CampaignTypeEnum_1.CampaignTypeEnum.ROLLOUT || campaign.getType() === CampaignTypeEnum_1.CampaignTypeEnum.PERSONALIZE; // get salt var salt = isRolloutOrPersonalize ? campaign.getVariations()[0].getSalt() : campaign.getSalt(); // get bucket key var bucketKey = salt ? "".concat(salt, "_").concat(userId) : "".concat(campaign.getId(), "_").concat(userId); // Return a seed combining campaign ID and user ID otherwise return bucketKey; } /** * Retrieves a variation by its ID within a specific campaign identified by its key. * @param {SettingsModel} settings - The settings model containing all campaigns. * @param {string} campaignKey - The key of the campaign. * @param {string} variationId - The ID of the variation to retrieve. * @returns {VariationModel | null} The found variation model or null if not found. */ function getVariationFromCampaignKey(settings, campaignKey, variationId) { // Find the campaign by its key var campaign = settings.getCampaigns().find(function (campaign) { return campaign.getKey() === campaignKey; }); if (campaign) { // Find the variation by its ID within the found campaign var variation = campaign.getVariations().find(function (variation) { return variation.getId() === variationId; }); if (variation) { // Return a new instance of VariationModel based on the found variation return new VariationModel_1.VariationModel().modelFromDictionary(variation); } } return null; } /** * Sets the allocation ranges for a list of campaigns. * @param {CampaignModel[]} campaigns - The list of campaigns to set allocations for. */ function setCampaignAllocation(campaigns) { var stepFactor = 0; for (var i = 0, currentAllocation = 0; i < campaigns.length; i++) { var campaign = campaigns[i]; // Assign range values to each campaign and update the current allocation stepFactor = assignRangeValuesMEG(campaign, currentAllocation); currentAllocation += stepFactor; } } /** * Determines if a campaign is part of a group. * @param {SettingsModel} settings - The settings model containing group associations. * @param {string} campaignId - The ID of the campaign to check. * @param {any} [variationId=null] - The optional variation ID. * @returns {Object} An object containing the group ID and name if the campaign is part of a group, otherwise an empty object. */ function getGroupDetailsIfCampaignPartOfIt(settings, campaignId, variationId) { if (variationId === void 0) { variationId = null; } /** * If variationId is null, that means that campaign is testing campaign * If variationId is not null, that means that campaign is personalization campaign and we need to append variationId to campaignId using _ * then check if the current campaign is part of any group */ var campaignToCheck = campaignId.toString(); // check if variationId is not null if (variationId !== null) { // if variationId is not null, then append it to the campaignId like campaignId_variationId campaignToCheck = "".concat(campaignId, "_").concat(variationId).toString(); } if (settings.getCampaignGroups() && Object.prototype.hasOwnProperty.call(settings.getCampaignGroups(), campaignToCheck)) { return { groupId: settings.getCampaignGroups()[campaignToCheck], groupName: settings.getGroups()[settings.getCampaignGroups()[campaignToCheck]].name, }; } return {}; } /** * Retrieves campaigns by a specific group ID. * @param {SettingsModel} settings - The settings model containing all groups. * @param {any} groupId - The ID of the group. * @returns {Array} An array of campaigns associated with the specified group ID. */ function getCampaignsByGroupId(settings, groupId) { var group = settings.getGroups()[groupId]; if (group) { return group.campaigns; // Return the campaigns associated with the group } else { return []; // Return an empty array if the group ID is not found } } /** * Retrieves feature keys from a list of campaign IDs. * @param {SettingsModel} settings - The settings model containing all features. * @param {any} campaignIdWithVariation - An array of campaign IDs and variation IDs in format campaignId_variationId. * @returns {Array} An array of feature keys associated with the provided campaign IDs. */ function getFeatureKeysFromCampaignIds(settings, campaignIdWithVariation) { var featureKeys = []; var _loop_1 = function (campaign) { // split key with _ to separate campaignId and variationId var _a = campaign.split('_').map(Number), campaignId = _a[0], variationId = _a[1]; settings.getFeatures().forEach(function (feature) { // check if feature already exists in the featureKeys array if (featureKeys.indexOf(feature.getKey()) !== -1) { return; } feature.getRules().forEach(function (rule) { if (rule.getCampaignId() === campaignId) { // Check if variationId is provided and matches the rule's variationId if (variationId !== undefined && variationId !== null) { // Add feature key if variationId matches if (rule.getVariationId() === variationId) { featureKeys.push(feature.getKey()); } } else { // Add feature key if no variationId is provided featureKeys.push(feature.getKey()); } } }); }); }; for (var _i = 0, campaignIdWithVariation_1 = campaignIdWithVariation; _i < campaignIdWithVariation_1.length; _i++) { var campaign = campaignIdWithVariation_1[_i]; _loop_1(campaign); } return featureKeys; } /** * Retrieves campaign IDs from a specific feature key. * @param {SettingsModel} settings - The settings model containing all features. * @param {string} featureKey - The key of the feature. * @returns {Array} An array of campaign IDs associated with the specified feature key. */ function getCampaignIdsFromFeatureKey(settings, featureKey) { var campaignIds = []; settings.getFeatures().forEach(function (feature) { if (feature.getKey() === featureKey) { feature.getRules().forEach(function (rule) { campaignIds.push(rule.getCampaignId()); // Add campaign ID if feature key matches }); } }); return campaignIds; } /** * Assigns range values to a campaign based on its weight. * @param {any} data - The campaign data containing weight. * @param {number} currentAllocation - The current allocation value before this campaign. * @returns {number} The step factor calculated from the campaign's weight. */ function assignRangeValuesMEG(data, currentAllocation) { var stepFactor = _getVariationBucketRange(data.weight); if (stepFactor) { data.startRangeVariation = currentAllocation + 1; // Set the start range data.endRangeVariation = currentAllocation + stepFactor; // Set the end range } else { data.startRangeVariation = -1; // Set invalid range if step factor is zero data.endRangeVariation = -1; } return stepFactor; } /** * Calculates the bucket range for a variation based on its weight. * @param {number} variationWeight - The weight of the variation. * @returns {number} The calculated bucket range. */ function _getVariationBucketRange(variationWeight) { if (!variationWeight || variationWeight === 0) { return 0; // Return zero if weight is invalid or zero } var startRange = Math.ceil(variationWeight * 100); return Math.min(startRange, constants_1.Constants.MAX_TRAFFIC_VALUE); // Ensure the range does not exceed the max traffic value } /** * Handles the rollout campaign by setting start and end ranges for all variations. * @param {CampaignModel} campaign - The campaign to handle. */ function _handleRolloutCampaign(campaign) { // Set start and end ranges for all variations in the campaign for (var i = 0; i < campaign.getVariations().length; i++) { var variation = campaign.getVariations()[i]; var endRange = campaign.getVariations()[i].getWeight() * 100; variation.setStartRange(1); variation.setEndRange(endRange); logger_1.LogManager.Instance.info((0, LogMessageUtil_1.buildMessage)(log_messages_1.InfoLogMessagesEnum.VARIATION_RANGE_ALLOCATION, { variationKey: variation.getKey(), campaignKey: campaign.getKey(), variationWeight: variation.getWeight(), startRange: 1, endRange: endRange, })); } } //# sourceMappingURL=CampaignUtil.js.map