UNPKG

@splitsoftware/splitio-commons

Version:
165 lines (164 loc) 9.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clientFactory = exports.stringify = void 0; var evaluator_1 = require("../evaluator"); var thenable_1 = require("../utils/promise/thenable"); var key_1 = require("../utils/key"); var definitionExistence_1 = require("../utils/inputValidation/definitionExistence"); var labels_1 = require("../utils/labels"); var constants_1 = require("../utils/constants"); var constants_2 = require("../logger/constants"); var mode_1 = require("../utils/settingsValidation/mode"); var trackMethod_1 = require("./trackMethod"); var treatmentNotReady = { treatment: constants_1.CONTROL, label: labels_1.SDK_NOT_READY }; function treatmentsNotReady(featureFlagNames) { var evaluations = {}; featureFlagNames.forEach(function (featureFlagName) { evaluations[featureFlagName] = treatmentNotReady; }); return evaluations; } function stringify(options) { if (options && options.properties) { try { return JSON.stringify(options.properties); } catch ( /* JSON.stringify should never throw with validated options, but handling just in case */_a) { /* JSON.stringify should never throw with validated options, but handling just in case */ } } } exports.stringify = stringify; /** * Creator of base client with getTreatments and track methods. */ function clientFactory(params) { var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, settings = params.settings, impressionsTracker = params.impressionsTracker, telemetryTracker = params.telemetryTracker, fallbackCalculator = params.fallbackCalculator; var log = settings.log, mode = settings.mode; var isAsync = (0, mode_1.isConsumerMode)(mode); function getTreatment(key, featureFlagName, attributes, options, withConfig, methodName) { if (withConfig === void 0) { withConfig = false; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENT; } var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? constants_1.TREATMENT_WITH_CONFIG : constants_1.TREATMENT); var wrapUp = function (evaluationResult) { var queue = []; var treatment = processEvaluation(evaluationResult, featureFlagName, key, stringify(options), withConfig, methodName, queue); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatment; }; var evaluation = readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeature)(log, key, featureFlagName, attributes, storage, options) : isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected Promise.resolve(treatmentNotReady) : treatmentNotReady; return (0, thenable_1.thenable)(evaluation) ? evaluation.then(function (res) { return wrapUp(res); }) : wrapUp(evaluation); } function getTreatmentWithConfig(key, featureFlagName, attributes, options) { return getTreatment(key, featureFlagName, attributes, options, true, constants_1.GET_TREATMENT_WITH_CONFIG); } function getTreatments(key, featureFlagNames, attributes, options, withConfig, methodName) { if (withConfig === void 0) { withConfig = false; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENTS; } var stopTelemetryTracker = telemetryTracker.trackEval(withConfig ? constants_1.TREATMENTS_WITH_CONFIG : constants_1.TREATMENTS); var wrapUp = function (evaluationResults) { var queue = []; var treatments = {}; var properties = stringify(options); Object.keys(evaluationResults).forEach(function (featureFlagName) { treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatments; }; var evaluations = readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeatures)(log, key, featureFlagNames, attributes, storage, options) : isAsync ? // If the SDK is not ready, treatment may be incorrect due to having splits but not segments data, or storage is not connected Promise.resolve(treatmentsNotReady(featureFlagNames)) : treatmentsNotReady(featureFlagNames); return (0, thenable_1.thenable)(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations); } function getTreatmentsWithConfig(key, featureFlagNames, attributes, options) { return getTreatments(key, featureFlagNames, attributes, options, true, constants_1.GET_TREATMENTS_WITH_CONFIG); } function getTreatmentsByFlagSets(key, flagSetNames, attributes, options, withConfig, method, methodName) { if (withConfig === void 0) { withConfig = false; } if (method === void 0) { method = constants_1.TREATMENTS_BY_FLAGSETS; } if (methodName === void 0) { methodName = constants_1.GET_TREATMENTS_BY_FLAG_SETS; } var stopTelemetryTracker = telemetryTracker.trackEval(method); var wrapUp = function (evaluationResults) { var queue = []; var treatments = {}; var properties = stringify(options); Object.keys(evaluationResults).forEach(function (featureFlagName) { treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, properties, withConfig, methodName, queue); }); impressionsTracker.track(queue, attributes); stopTelemetryTracker(queue[0] && queue[0].imp.label); return treatments; }; var evaluations = readinessManager.isReadyFromCache() ? (0, evaluator_1.evaluateFeaturesByFlagSets)(log, key, flagSetNames, attributes, storage, methodName, options) : isAsync ? Promise.resolve({}) : {}; return (0, thenable_1.thenable)(evaluations) ? evaluations.then(function (res) { return wrapUp(res); }) : wrapUp(evaluations); } function getTreatmentsWithConfigByFlagSets(key, flagSetNames, attributes, options) { return getTreatmentsByFlagSets(key, flagSetNames, attributes, options, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSETS, constants_1.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS); } function getTreatmentsByFlagSet(key, flagSetName, attributes, options) { return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, false, constants_1.TREATMENTS_BY_FLAGSET, constants_1.GET_TREATMENTS_BY_FLAG_SET); } function getTreatmentsWithConfigByFlagSet(key, flagSetName, attributes, options) { return getTreatmentsByFlagSets(key, [flagSetName], attributes, options, true, constants_1.TREATMENTS_WITH_CONFIG_BY_FLAGSET, constants_1.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET); } // Internal function function processEvaluation(evaluation, featureFlagName, key, properties, withConfig, invokingMethodName, queue) { var matchingKey = (0, key_1.getMatching)(key); var bucketingKey = (0, key_1.getBucketing)(key); var changeNumber = evaluation.changeNumber, impressionsDisabled = evaluation.impressionsDisabled; var treatment = evaluation.treatment, label = evaluation.label, _a = evaluation.config, config = _a === void 0 ? null : _a; if (treatment === constants_1.CONTROL) { var fallbackTreatment = fallbackCalculator(featureFlagName, label); treatment = fallbackTreatment.treatment; label = fallbackTreatment.label; config = fallbackTreatment.config; } if ((0, definitionExistence_1.validateDefinitionExistence)(log, readinessManager, featureFlagName, label, invokingMethodName)) { log.info(constants_2.IMPRESSION_QUEUEING, ['Feature flag', featureFlagName, matchingKey, treatment, label]); queue.push({ imp: { feature: featureFlagName, keyName: matchingKey, treatment: treatment, time: Date.now(), bucketingKey: bucketingKey, label: label, changeNumber: changeNumber, properties: properties }, disabled: impressionsDisabled }); } if (withConfig) { return { treatment: treatment, config: config }; } return treatment; } var track = (0, trackMethod_1.trackMethodFactory)(params); return { getTreatment: getTreatment, getTreatmentWithConfig: getTreatmentWithConfig, getTreatments: getTreatments, getTreatmentsWithConfig: getTreatmentsWithConfig, getTreatmentsByFlagSets: getTreatmentsByFlagSets, getTreatmentsWithConfigByFlagSets: getTreatmentsWithConfigByFlagSets, getTreatmentsByFlagSet: getTreatmentsByFlagSet, getTreatmentsWithConfigByFlagSet: getTreatmentsWithConfigByFlagSet, track: track, }; } exports.clientFactory = clientFactory;