vwo-fme-node-sdk 1.55.0 → 1.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/VERSION.js +1 -1
  3. package/dist/client/vwo-fme-javascript-sdk.js +266 -10
  4. package/dist/client/vwo-fme-javascript-sdk.js.map +1 -1
  5. package/dist/client/vwo-fme-javascript-sdk.min.js +2 -2
  6. package/dist/client/vwo-fme-javascript-sdk.min.js.map +1 -1
  7. package/dist/esm/models/user/ContextModel.js +9 -0
  8. package/dist/esm/models/user/ContextModel.js.map +1 -1
  9. package/dist/esm/packages/logger/core/LogManager.js +1 -1
  10. package/dist/esm/packages/logger/core/LogManager.js.map +1 -1
  11. package/dist/esm/packages/segmentation-evaluator/core/SegmentationManger.js +33 -2
  12. package/dist/esm/packages/segmentation-evaluator/core/SegmentationManger.js.map +1 -1
  13. package/dist/esm/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.js +2 -0
  14. package/dist/esm/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.js.map +1 -1
  15. package/dist/esm/packages/segmentation-evaluator/evaluators/SegmentEvaluator.js +2 -0
  16. package/dist/esm/packages/segmentation-evaluator/evaluators/SegmentEvaluator.js.map +1 -1
  17. package/dist/esm/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.js +51 -1
  18. package/dist/esm/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.js.map +1 -1
  19. package/dist/esm/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.js +130 -0
  20. package/dist/esm/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.js.map +1 -0
  21. package/dist/package.json +1 -1
  22. package/dist/server/vwo-fme-node-sdk.js +304 -9
  23. package/dist/server/vwo-fme-node-sdk.js.map +1 -1
  24. package/dist/server/vwo-fme-node-sdk.min.js +2 -2
  25. package/dist/server/vwo-fme-node-sdk.min.js.map +1 -1
  26. package/dist/server-unpacked/models/user/ContextModel.js +20 -0
  27. package/dist/server-unpacked/models/user/ContextModel.js.map +1 -1
  28. package/dist/server-unpacked/packages/logger/core/LogManager.js +1 -1
  29. package/dist/server-unpacked/packages/logger/core/LogManager.js.map +1 -1
  30. package/dist/server-unpacked/packages/segmentation-evaluator/core/SegmentationManger.js +39 -4
  31. package/dist/server-unpacked/packages/segmentation-evaluator/core/SegmentationManger.js.map +1 -1
  32. package/dist/server-unpacked/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.js +2 -0
  33. package/dist/server-unpacked/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.js.map +1 -1
  34. package/dist/server-unpacked/packages/segmentation-evaluator/evaluators/SegmentEvaluator.js +4 -2
  35. package/dist/server-unpacked/packages/segmentation-evaluator/evaluators/SegmentEvaluator.js.map +1 -1
  36. package/dist/server-unpacked/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.js +50 -0
  37. package/dist/server-unpacked/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.js.map +1 -1
  38. package/dist/server-unpacked/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.js +137 -0
  39. package/dist/server-unpacked/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.js.map +1 -0
  40. package/dist/types/models/user/ContextModel.d.ts +10 -0
  41. package/dist/types/packages/segmentation-evaluator/core/SegmentationManger.d.ts +6 -0
  42. package/dist/types/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.d.ts +1 -0
  43. package/dist/types/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.d.ts +8 -0
  44. package/dist/types/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.d.ts +49 -0
  45. package/lib/models/user/ContextModel.ts +19 -0
  46. package/lib/packages/logger/core/LogManager.ts +1 -1
  47. package/lib/packages/segmentation-evaluator/core/SegmentationManger.ts +29 -2
  48. package/lib/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.ts +2 -0
  49. package/lib/packages/segmentation-evaluator/evaluators/SegmentEvaluator.ts +2 -0
  50. package/lib/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.ts +72 -1
  51. package/lib/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.ts +179 -0
  52. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.60.0] - 2026-06-29
9
+
10
+ ### Added
11
+
12
+ - Support for **Web Testing pre-segmentation**: campaign segmentation can use the `campaignVariation` operand. The SDK evaluates it against **`context.platformVariables.webTestingCampaigns`**, a map of Web Testing campaign ID → variation ID (plain object or JSON string). The customer must pass this data in the context to enable web testing pre-segmentation. Supported operand values in settings: `122` (user in campaign), `122_2` (exact variation), `122_!1` (in campaign but not variation 1), `!122` (not in campaign).
13
+
14
+ Example usage:
15
+
16
+ ```javascript
17
+ const context = {
18
+ id: 'user-123',
19
+ platformVariables: {
20
+ // This is an example, replace with actual object
21
+ webTestingCampaigns: {
22
+ 123: '4',
23
+ 456: '1',
24
+ },
25
+ },
26
+ };
27
+
28
+ const flag = await wingifyClient.getFlag('feature-key', context);
29
+ ```
30
+
8
31
  ## [1.55.0] - 2026-06-09
9
32
 
10
33
  ### Added
package/dist/VERSION.js CHANGED
@@ -1 +1 @@
1
- module.exports = { version: "1.55.0" };
1
+ module.exports = { version: "1.60.0" };
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * vwo-fme-javascript-sdk - v1.55.0
2
+ * vwo-fme-javascript-sdk - v1.60.0
3
3
  * URL - https://github.com/wingify/vwo-fme-javascript-sdk
4
4
  *
5
5
  * Copyright 2024-2026 Wingify Software Pvt. Ltd.
@@ -46,7 +46,7 @@ return /******/ (() => { // webpackBootstrap
46
46
  /***/ ((module) => {
47
47
 
48
48
  module.exports = {
49
- version: "1.55.0"
49
+ version: "1.60.0"
50
50
  };
51
51
 
52
52
  /***/ }),
@@ -4389,10 +4389,21 @@ exports.SettingsModel = SettingsModel;
4389
4389
  /*!*****************************************!*\
4390
4390
  !*** ./lib/models/user/ContextModel.ts ***!
4391
4391
  \*****************************************/
4392
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
4392
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
4393
4393
 
4394
4394
  "use strict";
4395
4395
 
4396
+ var __assign = (this && this.__assign) || function () {
4397
+ __assign = Object.assign || function(t) {
4398
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4399
+ s = arguments[i];
4400
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
4401
+ t[p] = s[p];
4402
+ }
4403
+ return t;
4404
+ };
4405
+ return __assign.apply(this, arguments);
4406
+ };
4396
4407
  Object.defineProperty(exports, "__esModule", ({ value: true }));
4397
4408
  exports.ContextModel = void 0;
4398
4409
  var ContextWingifyModel_1 = __webpack_require__(/*! ./ContextWingifyModel */ "./lib/models/user/ContextWingifyModel.ts");
@@ -4426,6 +4437,9 @@ var ContextModel = /** @class */ (function () {
4426
4437
  if (context === null || context === void 0 ? void 0 : context.bucketingSeed) {
4427
4438
  this.bucketingSeed = context.bucketingSeed;
4428
4439
  }
4440
+ if (context === null || context === void 0 ? void 0 : context.platformVariables) {
4441
+ this.platformVariables = __assign({}, context.platformVariables);
4442
+ }
4429
4443
  if (context === null || context === void 0 ? void 0 : context.isDevMode) {
4430
4444
  this.isDevMode = context.isDevMode === true;
4431
4445
  }
@@ -4485,6 +4499,12 @@ var ContextModel = /** @class */ (function () {
4485
4499
  var _a;
4486
4500
  return (_a = this.bucketingSeed) === null || _a === void 0 ? void 0 : _a.toString();
4487
4501
  };
4502
+ ContextModel.prototype.getPlatformVariables = function () {
4503
+ return this.platformVariables;
4504
+ };
4505
+ ContextModel.prototype.setPlatformVariables = function (platformVariables) {
4506
+ this.platformVariables = platformVariables;
4507
+ };
4488
4508
  ContextModel.prototype.getIsDevMode = function () {
4489
4509
  return this.isDevMode === true;
4490
4510
  };
@@ -4950,7 +4970,7 @@ var LogManager = /** @class */ (function (_super) {
4950
4970
  try {
4951
4971
  var message = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum[template], data);
4952
4972
  this.error(message);
4953
- if (shouldSendToWingify) {
4973
+ if (shouldSendToWingify && this.serviceContainer) {
4954
4974
  var debugEventProps = __assign(__assign(__assign({}, debugData), data), { msg_t: template, msg: message, lt: LogLevelEnum_1.LogLevelEnum.ERROR.toString(), cg: DebuggerCategoryEnum_1.DebuggerCategoryEnum.ERROR });
4955
4975
  // send debug event to Wingify
4956
4976
  (0, DebuggerServiceUtil_1.sendDebugEventToWingify)(this.serviceContainer, debugEventProps);
@@ -6496,6 +6516,7 @@ var DataTypeUtil_1 = __webpack_require__(/*! ../../../utils/DataTypeUtil */ "./l
6496
6516
  var ApiEnum_1 = __webpack_require__(/*! ../../../enums/ApiEnum */ "./lib/enums/ApiEnum.ts");
6497
6517
  var FunctionUtil_1 = __webpack_require__(/*! ../../../utils/FunctionUtil */ "./lib/utils/FunctionUtil.ts");
6498
6518
  var SegmentOperandEvaluator_1 = __webpack_require__(/*! ../evaluators/SegmentOperandEvaluator */ "./lib/packages/segmentation-evaluator/evaluators/SegmentOperandEvaluator.ts");
6519
+ var SegmentOperatorValueEnum_1 = __webpack_require__(/*! ../enums/SegmentOperatorValueEnum */ "./lib/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.ts");
6499
6520
  var SegmentationManager = /** @class */ (function () {
6500
6521
  /**
6501
6522
  * Constructor for SegmentationManager.
@@ -6567,14 +6588,48 @@ var SegmentationManager = /** @class */ (function () {
6567
6588
  */
6568
6589
  SegmentationManager.prototype.validateSegmentation = function (dsl, properties) {
6569
6590
  return __awaiter(this, void 0, void 0, function () {
6570
- return __generator(this, function (_a) {
6571
- switch (_a.label) {
6572
- case 0: return [4 /*yield*/, this.evaluator.isSegmentationValid(dsl, properties)];
6573
- case 1: return [2 /*return*/, _a.sent()]; // Delegate to evaluator's method
6591
+ var _a, _b;
6592
+ return __generator(this, function (_c) {
6593
+ switch (_c.label) {
6594
+ case 0:
6595
+ // If the DSL contains any campaignVariation node but no webTestingCampaigns was provided, fail immediately.
6596
+ // This covers NOT/OR/AND wrappers too — there is no web testing data to evaluate against.
6597
+ if (this.hasCampaignVariationNode(dsl) && !((_b = (_a = this.evaluator.context) === null || _a === void 0 ? void 0 : _a.getPlatformVariables()) === null || _b === void 0 ? void 0 : _b.webTestingCampaigns)) {
6598
+ return [2 /*return*/, false];
6599
+ }
6600
+ return [4 /*yield*/, this.evaluator.isSegmentationValid(dsl, properties)];
6601
+ case 1: return [2 /*return*/, _c.sent()];
6574
6602
  }
6575
6603
  });
6576
6604
  });
6577
6605
  };
6606
+ /**
6607
+ * Recursively checks if any node in the DSL tree is a campaignVariation operand.
6608
+ * @param {Record<string, dynamic>} dsl - The segmentation DSL to check.
6609
+ * @returns {boolean} True if the DSL contains a campaignVariation node, otherwise false.
6610
+ */
6611
+ SegmentationManager.prototype.hasCampaignVariationNode = function (dsl) {
6612
+ if (!(0, DataTypeUtil_1.isObject)(dsl))
6613
+ return false;
6614
+ for (var _i = 0, _a = Object.keys(dsl); _i < _a.length; _i++) {
6615
+ var operator = _a[_i];
6616
+ if (operator === SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.WEB_CAMPAIGN_VARIATION)
6617
+ return true;
6618
+ var operand = dsl[operator];
6619
+ if (Array.isArray(operand)) {
6620
+ for (var _b = 0, operand_1 = operand; _b < operand_1.length; _b++) {
6621
+ var subDsl = operand_1[_b];
6622
+ if (this.hasCampaignVariationNode(subDsl))
6623
+ return true;
6624
+ }
6625
+ }
6626
+ else if ((0, DataTypeUtil_1.isObject)(operand)) {
6627
+ if (this.hasCampaignVariationNode(operand))
6628
+ return true;
6629
+ }
6630
+ }
6631
+ return false;
6632
+ };
6578
6633
  return SegmentationManager;
6579
6634
  }());
6580
6635
  exports.SegmentationManager = SegmentationManager;
@@ -6712,6 +6767,8 @@ var SegmentOperatorValueEnum;
6712
6767
  SegmentOperatorValueEnum["IP"] = "ip_address";
6713
6768
  SegmentOperatorValueEnum["BROWSER_VERSION"] = "browser_version";
6714
6769
  SegmentOperatorValueEnum["OS_VERSION"] = "os_version";
6770
+ // Pre-segment on Web Testing campaign/variation assignment.
6771
+ SegmentOperatorValueEnum["WEB_CAMPAIGN_VARIATION"] = "campaignVariation";
6715
6772
  })(SegmentOperatorValueEnum || (exports.SegmentOperatorValueEnum = SegmentOperatorValueEnum = {}));
6716
6773
 
6717
6774
 
@@ -6814,8 +6871,9 @@ var SegmentEvaluator = /** @class */ (function () {
6814
6871
  case SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.IP: return [3 /*break*/, 11];
6815
6872
  case SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.BROWSER_VERSION: return [3 /*break*/, 12];
6816
6873
  case SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.OS_VERSION: return [3 /*break*/, 13];
6874
+ case SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.WEB_CAMPAIGN_VARIATION: return [3 /*break*/, 14];
6817
6875
  }
6818
- return [3 /*break*/, 14];
6876
+ return [3 /*break*/, 15];
6819
6877
  case 1: return [4 /*yield*/, this.isSegmentationValid(subDsl, properties)];
6820
6878
  case 2: return [2 /*return*/, !(_c.sent())];
6821
6879
  case 3: return [4 /*yield*/, this.every(subDsl, properties)];
@@ -6829,7 +6887,8 @@ var SegmentEvaluator = /** @class */ (function () {
6829
6887
  case 11: return [2 /*return*/, this.segmentOperandEvaluator.evaluateStringOperandDSL(subDsl, this.context, SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.IP)];
6830
6888
  case 12: return [2 /*return*/, this.segmentOperandEvaluator.evaluateStringOperandDSL(subDsl, this.context, SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.BROWSER_VERSION)];
6831
6889
  case 13: return [2 /*return*/, this.segmentOperandEvaluator.evaluateStringOperandDSL(subDsl, this.context, SegmentOperatorValueEnum_1.SegmentOperatorValueEnum.OS_VERSION)];
6832
- case 14: return [2 /*return*/, false];
6890
+ case 14: return [2 /*return*/, this.segmentOperandEvaluator.evaluateCampaignVariationDSL(subDsl, this.context)];
6891
+ case 15: return [2 /*return*/, false];
6833
6892
  }
6834
6893
  });
6835
6894
  });
@@ -7244,6 +7303,7 @@ exports.SegmentOperandEvaluator = void 0;
7244
7303
  * limitations under the License.
7245
7304
  */
7246
7305
  var SegmentUtil_1 = __webpack_require__(/*! ../utils/SegmentUtil */ "./lib/packages/segmentation-evaluator/utils/SegmentUtil.ts");
7306
+ var WebTestingSegmentUtil_1 = __webpack_require__(/*! ../utils/WebTestingSegmentUtil */ "./lib/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.ts");
7247
7307
  var SegmentOperandValueEnum_1 = __webpack_require__(/*! ../enums/SegmentOperandValueEnum */ "./lib/packages/segmentation-evaluator/enums/SegmentOperandValueEnum.ts");
7248
7308
  var SegmentOperandRegexEnum_1 = __webpack_require__(/*! ../enums/SegmentOperandRegexEnum */ "./lib/packages/segmentation-evaluator/enums/SegmentOperandRegexEnum.ts");
7249
7309
  var SegmentOperatorValueEnum_1 = __webpack_require__(/*! ../enums/SegmentOperatorValueEnum */ "./lib/packages/segmentation-evaluator/enums/SegmentOperatorValueEnum.ts");
@@ -7361,6 +7421,55 @@ var SegmentOperandEvaluator = /** @class */ (function () {
7361
7421
  tagValue = processedValues.tagValue; // Fix: Type assertion to ensure tagValue is of type string
7362
7422
  return this.extractResult(operandType, processedValues.operandValue, tagValue);
7363
7423
  };
7424
+ /**
7425
+ * Evaluates Web Testing pre-segmentation against `context.platformVariables.webTestingCampaigns`.
7426
+ * Operand: "C" (in Campaign, any variation), "C_V", "C_!V", "!C" (not in Campaign C).
7427
+ * @param {unknown} campaignVariationOperand - The DSL operand string representing the campaign variation.
7428
+ * @param {ContextModel} context - The context model containing platform variables for the evaluation.
7429
+ * @returns {boolean} True if the user matches the web testing campaign variation condition, otherwise false.
7430
+ */
7431
+ SegmentOperandEvaluator.prototype.evaluateCampaignVariationDSL = function (campaignVariationOperand, context) {
7432
+ // Settings JSON often deserializes campaign ids as numbers; coerce before matching DSL tokens.
7433
+ var operandString;
7434
+ if ((0, DataTypeUtil_1.isNumber)(campaignVariationOperand) && Number.isFinite(campaignVariationOperand)) {
7435
+ operandString = String(campaignVariationOperand);
7436
+ }
7437
+ else if ((0, DataTypeUtil_1.isString)(campaignVariationOperand)) {
7438
+ operandString = campaignVariationOperand;
7439
+ }
7440
+ if ((0, DataTypeUtil_1.isUndefined)(operandString)) {
7441
+ var type = (0, DataTypeUtil_1.getType)(campaignVariationOperand).toLowerCase();
7442
+ this.serviceContainer
7443
+ .getLogManager()
7444
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGN_VARIATION_OPERAND_TYPE', { type: type }, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7445
+ return false;
7446
+ }
7447
+ // Empty operand is invalid.
7448
+ if (operandString.length === 0) {
7449
+ this.serviceContainer
7450
+ .getLogManager()
7451
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGN_VARIATION_OPERAND_EMPTY', {}, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7452
+ return false;
7453
+ }
7454
+ var trimmedCampaignVariationOperand = operandString.trim();
7455
+ // All spaces is invalid.
7456
+ if (trimmedCampaignVariationOperand.length === 0) {
7457
+ this.serviceContainer
7458
+ .getLogManager()
7459
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGN_VARIATION_OPERAND_EMPTY', {}, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7460
+ return false;
7461
+ }
7462
+ // Parse the campaigns from the context.
7463
+ var assignedVariationsByCampaignId = (0, WebTestingSegmentUtil_1.parseWebTestingCampaignsFromContext)(context, this.serviceContainer);
7464
+ var _a = (0, WebTestingSegmentUtil_1.evaluateWebTestingCampaignVariation)(trimmedCampaignVariationOperand, assignedVariationsByCampaignId), result = _a.result, invalidFormat = _a.invalidFormat;
7465
+ // Invalid format of the operand.
7466
+ if (invalidFormat) {
7467
+ this.serviceContainer
7468
+ .getLogManager()
7469
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGN_VARIATION_OPERAND_FORMAT', { operand: trimmedCampaignVariationOperand }, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7470
+ }
7471
+ return result;
7472
+ };
7364
7473
  /**
7365
7474
  * Pre-processes the tag value to ensure it is in the correct format for evaluation.
7366
7475
  * @param {any} tagValue - The value to be processed.
@@ -7758,6 +7867,153 @@ function matchWithRegex(string, regex) {
7758
7867
  }
7759
7868
 
7760
7869
 
7870
+ /***/ }),
7871
+
7872
+ /***/ "./lib/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.ts":
7873
+ /*!****************************************************************************!*\
7874
+ !*** ./lib/packages/segmentation-evaluator/utils/WebTestingSegmentUtil.ts ***!
7875
+ \****************************************************************************/
7876
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
7877
+
7878
+ "use strict";
7879
+
7880
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
7881
+ exports.normalizeWebTestingCampaignsMap = normalizeWebTestingCampaignsMap;
7882
+ exports.parseWebTestingCampaignsFromContext = parseWebTestingCampaignsFromContext;
7883
+ exports.evaluateWebTestingCampaignVariation = evaluateWebTestingCampaignVariation;
7884
+ var ApiEnum_1 = __webpack_require__(/*! ../../../enums/ApiEnum */ "./lib/enums/ApiEnum.ts");
7885
+ var DataTypeUtil_1 = __webpack_require__(/*! ../../../utils/DataTypeUtil */ "./lib/utils/DataTypeUtil.ts");
7886
+ /**
7887
+ * Normalizes Web Testing campaign map keys and variation values to strings.
7888
+ * @param {Record<string, unknown>} rawAssignments - The raw assignments map from the context.
7889
+ * @returns {Record<string, string>} - The normalized assignments map with campaignId as key and variationId as value.
7890
+ */
7891
+ function normalizeWebTestingCampaignsMap(rawAssignments) {
7892
+ // Turn the raw assignments map into a simple string map for regex matching.
7893
+ var campaignIdToVariationId = {};
7894
+ for (var _i = 0, _a = Object.keys(rawAssignments); _i < _a.length; _i++) {
7895
+ var campaignId = _a[_i];
7896
+ var assignedVariationId = rawAssignments[campaignId];
7897
+ if (!(0, DataTypeUtil_1.isUndefined)(assignedVariationId) &&
7898
+ !(0, DataTypeUtil_1.isNull)(assignedVariationId) &&
7899
+ String(campaignId).length > 0
7900
+ // Ignore empty keys; null/undefined variations mean nothing assigned for that id.
7901
+ ) {
7902
+ campaignIdToVariationId[String(campaignId)] = String(assignedVariationId);
7903
+ }
7904
+ }
7905
+ return campaignIdToVariationId;
7906
+ }
7907
+ /**
7908
+ * Parses `context.platformVariables.webTestingCampaigns` (JSON string or plain object).
7909
+ * @param {ContextModel} context - The context model containing platform variables for the evaluation.
7910
+ * @param {ServiceContainer} serviceContainer - The service container for accessing services like the log manager.
7911
+ * @returns {Record<string, string> | null} A record mapping campaign IDs to variation IDs, or null if invalid/missing.
7912
+ */
7913
+ function parseWebTestingCampaignsFromContext(context, serviceContainer) {
7914
+ var _a;
7915
+ var webTestingCampaignsInput = (_a = context.getPlatformVariables()) === null || _a === void 0 ? void 0 : _a.webTestingCampaigns;
7916
+ // No payload from the integration means empty assignments map.
7917
+ if ((0, DataTypeUtil_1.isNull)(webTestingCampaignsInput) || (0, DataTypeUtil_1.isUndefined)(webTestingCampaignsInput)) {
7918
+ return null;
7919
+ }
7920
+ // SDK already forwarded a plain campaignId -> variationId object.
7921
+ if ((0, DataTypeUtil_1.isObject)(webTestingCampaignsInput)) {
7922
+ return normalizeWebTestingCampaignsMap(webTestingCampaignsInput);
7923
+ }
7924
+ // Some stacks pass JSON text (cookie, SSR prop, tag); parse it only if it's an object.
7925
+ if ((0, DataTypeUtil_1.isString)(webTestingCampaignsInput)) {
7926
+ var trimmedWebTestingCampaignsJson = webTestingCampaignsInput.trim();
7927
+ if (trimmedWebTestingCampaignsJson === '') {
7928
+ // Empty JSON string is invalid.
7929
+ return null;
7930
+ }
7931
+ try {
7932
+ // extract all "key": tokens and check for duplicates before parsing swallows them
7933
+ var allCampaignIdTokens = trimmedWebTestingCampaignsJson.match(/"([^"\\]*)"\s*:/g);
7934
+ if (allCampaignIdTokens) {
7935
+ var campaignIds = allCampaignIdTokens.map(function (token) { return token.replace(/"\s*:$/, '').slice(1); });
7936
+ var hasDuplicateCampaignId = campaignIds.length !== new Set(campaignIds).size;
7937
+ if (hasDuplicateCampaignId) {
7938
+ serviceContainer
7939
+ .getLogManager()
7940
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGNS_DUPLICATE_KEY', {}, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7941
+ }
7942
+ }
7943
+ // Parse the JSON string into an object.
7944
+ var parsedAssignments = JSON.parse(trimmedWebTestingCampaignsJson);
7945
+ if ((0, DataTypeUtil_1.isObject)(parsedAssignments)) {
7946
+ return normalizeWebTestingCampaignsMap(parsedAssignments);
7947
+ }
7948
+ // Parsed fine but it's an array/string/etc. Invalid shape.
7949
+ serviceContainer
7950
+ .getLogManager()
7951
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGNS_JSON', {}, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7952
+ }
7953
+ catch (_b) {
7954
+ // Malformed JSON; treat like missing assignments.
7955
+ serviceContainer
7956
+ .getLogManager()
7957
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGNS_JSON', {}, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7958
+ }
7959
+ return null;
7960
+ }
7961
+ // Booleans/numbers/other odd types are invalid.
7962
+ if (!(0, DataTypeUtil_1.isUndefined)(webTestingCampaignsInput) && !(0, DataTypeUtil_1.isNull)(webTestingCampaignsInput)) {
7963
+ var kind = (0, DataTypeUtil_1.isArray)(webTestingCampaignsInput) ? 'array' : (0, DataTypeUtil_1.getType)(webTestingCampaignsInput).toLowerCase();
7964
+ serviceContainer
7965
+ .getLogManager()
7966
+ .errorLog('INVALID_WEB_TESTING_CAMPAIGNS_TYPE', { kind: kind }, { an: ApiEnum_1.ApiEnum.GET_FLAG, uuid: context.getUuid(), sId: context.getSessionId() });
7967
+ }
7968
+ return null;
7969
+ }
7970
+ /**
7971
+ * Evaluates campaignVariation operand encoding:
7972
+ * - "!C" — user is not in campaign C (no entry in map)
7973
+ * - "C_!V" — user is in campaign C and assigned variation is not V
7974
+ * - "C_V" — user is in campaign C with variation V
7975
+ * - "C" (digits only) — user is in campaign C (any variation)
7976
+ */
7977
+ function evaluateWebTestingCampaignVariation(campaignVariationOperand, assignedVariationsByCampaignId) {
7978
+ // Null means empty assignments map.
7979
+ var assignments = assignedVariationsByCampaignId !== null && assignedVariationsByCampaignId !== void 0 ? assignedVariationsByCampaignId : {};
7980
+ // !123 — user should not be in campaign 123.
7981
+ var match = /^!(\d+)$/.exec(campaignVariationOperand);
7982
+ if (match) {
7983
+ var campaignId = match[1];
7984
+ return { result: !Object.prototype.hasOwnProperty.call(assignments, campaignId), invalidFormat: false };
7985
+ }
7986
+ // 123_!4 — in campaign 123 but not the variation 4.
7987
+ match = /^(\d+)_!(\d+)$/.exec(campaignVariationOperand);
7988
+ if (match) {
7989
+ var campaignId = match[1];
7990
+ var variationId = match[2];
7991
+ if (!Object.prototype.hasOwnProperty.call(assignments, campaignId)) {
7992
+ return { result: false, invalidFormat: false };
7993
+ }
7994
+ return { result: assignments[campaignId] !== variationId, invalidFormat: false };
7995
+ }
7996
+ // 123_4 — must be exactly that campaign and variation.
7997
+ match = /^(\d+)_(\d+)$/.exec(campaignVariationOperand);
7998
+ if (match) {
7999
+ var campaignId = match[1];
8000
+ var variationId = match[2];
8001
+ if (!Object.prototype.hasOwnProperty.call(assignments, campaignId)) {
8002
+ return { result: false, invalidFormat: false };
8003
+ }
8004
+ return { result: assignments[campaignId] === variationId, invalidFormat: false };
8005
+ }
8006
+ // 123 — in the campaign, any variation counts.
8007
+ match = /^(\d+)$/.exec(campaignVariationOperand);
8008
+ if (match) {
8009
+ var campaignId = match[1];
8010
+ return { result: Object.prototype.hasOwnProperty.call(assignments, campaignId), invalidFormat: false };
8011
+ }
8012
+ // Invalid format.
8013
+ return { result: false, invalidFormat: true };
8014
+ }
8015
+
8016
+
7761
8017
  /***/ }),
7762
8018
 
7763
8019
  /***/ "./lib/packages/storage/Connector.ts":