UNPKG

vwo-fme-node-sdk

Version:

VWO Node/JavaScript SDK for Feature Management and Experimentation

1,040 lines (1,023 loc) 527 kB
/*! * vwo-fme-node-sdk - v1.21.0 * URL - https://github.com/wingify/vwo-node-sdk * * 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. * * Dependencies used - * 1. murmurhash - ^2.0.1 * 2. superstruct - ^0.14.x * 3. uuid - ^9.0.1 * 4. vwo-fme-sdk-log-messages - ^1.*.* */ /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./dist/package.json": /*!***************************!*\ !*** ./dist/package.json ***! \***************************/ /***/ ((module) => { module.exports = /*#__PURE__*/JSON.parse('{"name":"vwo-fme-node-sdk","version":"1.21.0","description":"VWO Node/JavaScript SDK for Feature Management and Experimentation","main":"dist/server/vwo-fme-node-sdk.min.js","browser":"dist/client/vwo-fme-javascript-sdk.min.js","exports":{".":{"node":{"types":"./dist/types/index.d.ts","import":"./dist/server/vwo-fme-node-sdk.min.js","require":"./dist/server/vwo-fme-node-sdk.min.js","default":"./dist/server/vwo-fme-node-sdk.min.js"},"default":{"types":"./dist/types/index.d.ts","import":"./dist/client/vwo-fme-javascript-sdk.js","require":"./dist/client/vwo-fme-javascript-sdk.min.js","default":"./dist/client/vwo-fme-javascript-sdk.min.js"}},"./node":{"types":"./dist/types/index.d.ts","import":"./dist/server/vwo-fme-node-sdk.min.js","require":"./dist/server/vwo-fme-node-sdk.min.js","default":"./dist/server/vwo-fme-node-sdk.min.js"},"./browser":{"types":"./dist/types/index.d.ts","import":"./dist/client/vwo-fme-javascript-sdk.js","require":"./dist/client/vwo-fme-javascript-sdk.min.js","default":"./dist/client/vwo-fme-javascript-sdk.min.js"}},"types":"dist/types/index.d.ts","scripts":{"build":"rm -rf dist/ yarn tsc:prod && yarn build:node && yarn build:browser && prettier -w dist/types/","build:browser":"yarn build:dev-browser && yarn build:prod-browser","build:node":"yarn build:dev-node && yarn build:prod-node","build:dev-browser":"webpack --config ./webpack.browser.config.js --mode=development","build:dev-node":"yarn tsc:prod && webpack --config ./webpack.node.config.js --mode=development","build:dev-browser-watch":"webpack --config ./webpack.browser.config.js --mode=development --watch","build:dev-node-watch":"yarn tsc:prod && webpack --config ./webpack.node.config.js --mode=development --watch","build:dev-browser-analyze":"webpack --config ./webpack.browser.config.js --mode=development --env analyze=1","build:dev-node-analyze":"yarn tsc:prod && webpack --config ./webpack.node.config.js --mode=production --env analyze=1","build:prod-browser":"webpack --config ./webpack.browser.config.js --mode=production","build:prod-node":"yarn tsc:prod && webpack --config ./webpack.node.config.js --mode=production","check:license":"yarn check:versions && node -e \'require(\\"./scripts/check-license\\")\'","check:versions":"node -e \'require(\\"./scripts/check-versions\\")\'","demo":"nodemon --inspect=0.0.0.0:9229 --legacy-watch --ignore node_modules demo/index.js","demo:server":"nodemon --inspect=0.0.0.0:9229 --legacy-watch --ignore node_modules demo/server.js","lint":"node -e \'require(\\"./scripts/check-versions\\")([\\"nodeLint\\"])\' && eslint lib/ --fix","lint:errors-only":"node -e \'require(\\"./scripts/check-versions\\")([\\"nodeLint\\"])\' && eslint **/*.ts\' --fix --quiet","prepare":"husky","prettier":"prettier -w lib/**/*.ts *.md","test:dev":"node --inspect-brk node_modules/jest/bin/jest.js --watch --runInBand --debug --colors --errorOnDeprecated","test:prod":"jest --runInBand --colors --errorOnDeprecated","test:coverage":"jest --coverage --coverageDirectory=coverage && cat ./coverage/lcov.info","tsc":"yarn check:versions && rm -rf dist/server-unpacked && cp package.json dist/ && tsc -w","tsc:prod":"yarn check:versions && rm -rf dist/server-unpacked && tsc && cp package.json dist/","typedoc":"typedoc --plugin typedoc-plugin-markdown --out ./docs lib/*.ts lib/**/*.ts lib/**/**/*.ts ","typedoc:html":"typedoc --out docs-html lib/*.ts lib/**/*.ts lib/**/**/*.ts"},"repository":{"type":"git","url":"https://github.com/wingify/vwo-fme-node-sdk"},"author":"VWO developers","license":"Apache-2.0","files":["dist/","package.json","yarn.lock","lib/**/*","LICENSE","README.md","CONTRIBUTING.md","CHANGELOG.md","NOTICE"],"dependencies":{"murmurhash":"^2.0.1","superstruct":"^0.14.x","uuid":"^9.0.1","vwo-fme-sdk-log-messages":"^1.*.*"},"devDependencies":{"@babel/core":"^7.24.5","@babel/preset-env":"^7.24.5","@babel/preset-typescript":"^7.24.1","@commitlint/cli":"^19.3.0","@commitlint/config-conventional":"^19.2.2","@eslint/js":"^9.2.0","@types/jest":"^29.5.12","@types/node":"^20.12.7","babel-jest":"^29.7.0","babel-loader":"^9.1.3","eslint":"^9.2.0","globals":"^15.1.0","husky":"^9.0.11","jest":"^29.7.0","lint-staged":"^15.2.2","nodemon":"^2.0.6","prettier":"^3.2.5","semver":"^7.6.0","shelljs":"^0.8.5","ts-loader":"^9.5.1","typedoc":"^0.25.13","typescript":"^5.4.5","typescript-eslint":"^7.8.0","vwo-fme-sdk-e2e-test-settings-n-cases":"^1.4.0","webpack":"^5.91.0","webpack-bundle-analyzer":"^4.10.2","webpack-cli":"^5.1.4","webpack-node-externals":"^3.0.0"},"lint-staged":{"**/*.{ts,json,md}":["prettier --write"]},"engineStrict":true,"engines":{"node":">= 8.9.0","yarn":">= 1.22.17"},"customEngines":{"nodeLint":">= 18.18.0"}}'); /***/ }), /***/ "./dist/server-unpacked/VWO.js": /*!*************************************!*\ !*** ./dist/server-unpacked/VWO.js ***! \*************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = this && this.__generator || function (thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.VWO = void 0; exports.init = init; exports.onInit = onInit; /** * 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 VWOBuilder_1 = __webpack_require__(/*! ./VWOBuilder */ "./dist/server-unpacked/VWOBuilder.js"); var DataTypeUtil_1 = __webpack_require__(/*! ./utils/DataTypeUtil */ "./dist/server-unpacked/utils/DataTypeUtil.js"); var PromiseUtil_1 = __webpack_require__(/*! ./utils/PromiseUtil */ "./dist/server-unpacked/utils/PromiseUtil.js"); var log_messages_1 = __webpack_require__(/*! ./enums/log-messages */ "./dist/server-unpacked/enums/log-messages/index.js"); var LogMessageUtil_1 = __webpack_require__(/*! ./utils/LogMessageUtil */ "./dist/server-unpacked/utils/LogMessageUtil.js"); var PlatformEnum_1 = __webpack_require__(/*! ./enums/PlatformEnum */ "./dist/server-unpacked/enums/PlatformEnum.js"); var ApiEnum_1 = __webpack_require__(/*! ./enums/ApiEnum */ "./dist/server-unpacked/enums/ApiEnum.js"); var VWO = /** @class */function () { /** * Constructor for the VWO class. * Initializes a new instance of VWO with the provided options. * @param {Record<string, dynamic>} options - Configuration options for the VWO instance. * @returns The instance of VWO. */ function VWO(options) { return VWO.setInstance(options); } /** * Sets the singleton instance of VWO. * Configures and builds the VWO instance using the provided options. * @param {Record<string, dynamic>} options - Configuration options for setting up VWO. * @returns A Promise resolving to the configured VWO instance. */ VWO.setInstance = function (options) { var _this = this; var optionsVWOBuilder = options === null || options === void 0 ? void 0 : options.vwoBuilder; this.vwoBuilder = optionsVWOBuilder || new VWOBuilder_1.VWOBuilder(options); this.instance = this.vwoBuilder.setLogger() // Sets up logging for debugging and monitoring. .setSettingsService() // Sets the settings service for configuration management. .setStorage() // Configures storage for data persistence. .setNetworkManager() // Configures network management for API communication. .setSegmentation() // Sets up segmentation for targeted functionality. // .initBatching() // Initializes batching for bulk data processing. .initPolling() // Starts polling mechanism for regular updates. .initBatching().initUsageStats(); // Initializes usage statistics for the SDK. // .setAnalyticsCallback() // Sets up analytics callback for data analysis. if (options === null || options === void 0 ? void 0 : options.settings) { return Promise.resolve(this.vwoBuilder.build(options.settings)); } return this.vwoBuilder.getSettings().then(function (settings) { return _this.vwoBuilder.build(settings); // Builds the VWO instance with the fetched settings. }); }; Object.defineProperty(VWO, "Instance", { /** * Gets the singleton instance of VWO. * @returns The singleton instance of VWO. */ get: function () { return this.instance; }, enumerable: false, configurable: true }); return VWO; }(); exports.VWO = VWO; var _global = {}; /** * Initializes a new instance of VWO with the provided options. * @param options Configuration options for the VWO instance. * @property {string} sdkKey - The SDK key for the VWO account. * @property {string} accountId - The account ID for the VWO account. * @property {GatewayServiceModel} gatewayService - The gateway service configuration. * @property {StorageService} storage - The storage configuration. * @returns */ function init(options) { return __awaiter(this, void 0, void 0, function () { var apiName, date, msg, msg, msg, instance, msg; return __generator(this, function (_a) { apiName = ApiEnum_1.ApiEnum.INIT; date = new Date().toISOString(); try { if (!(0, DataTypeUtil_1.isObject)(options)) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.INIT_OPTIONS_ERROR, { date: date }); console.error(msg); // Ensures options is an object. } if (!(options === null || options === void 0 ? void 0 : options.sdkKey) || !(0, DataTypeUtil_1.isString)(options === null || options === void 0 ? void 0 : options.sdkKey)) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.INIT_OPTIONS_SDK_KEY_ERROR, { date: date }); console.error(msg); // Validates sdkKey presence and type. } if (!options.accountId) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.INIT_OPTIONS_ACCOUNT_ID_ERROR, { date: date }); console.error(msg); // Validates accountId presence and type. } if (typeof process.env === 'undefined') { options.platform = PlatformEnum_1.PlatformEnum.CLIENT; } else { options.platform = PlatformEnum_1.PlatformEnum.SERVER; } instance = new VWO(options); _global = { vwoInitDeferred: new PromiseUtil_1.Deferred(), isSettingsFetched: false, instance: null }; return [2 /*return*/, instance.then(function (_vwoInstance) { _global.isSettingsFetched = true; _global.instance = _vwoInstance; _global.vwoInitDeferred.resolve(_vwoInstance); return _vwoInstance; })]; } catch (err) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_THROW_ERROR, { apiName: apiName, err: err }); console.info("[INFO]: VWO-SDK ".concat(new Date().toISOString(), " ").concat(msg)); } return [2 /*return*/]; }); }); } function onInit() { return __awaiter(this, void 0, void 0, function () { var apiName, date_1, msg, msg; return __generator(this, function (_a) { apiName = ApiEnum_1.ApiEnum.ON_INIT; try { _global.vwoInitDeferred = new PromiseUtil_1.Deferred(); date_1 = new Date().toISOString(); // If settings are already fetched, resolve the promise if (_global.isSettingsFetched) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.InfoLogMessagesEnum.ON_INIT_ALREADY_RESOLVED, { date: date_1, apiName: apiName }); console.info(msg); _global.vwoInitDeferred.resolve(_global.instance); } else { // wait for five seconds, else reject the promise setTimeout(function () { if (_global.isSettingsFetched) { return; } var msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.InfoLogMessagesEnum.ON_INIT_SETTINGS_FAILED, { date: date_1 }); console.error(msg); _global.vwoInitDeferred.reject(new Error('VWO settings could not be fetched')); }, 5000); } return [2 /*return*/, _global.vwoInitDeferred.promise]; } catch (err) { msg = (0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_THROW_ERROR, { apiName: apiName, err: err }); console.info("[INFO]: VWO-SDK ".concat(new Date().toISOString(), " ").concat(msg)); } return [2 /*return*/]; }); }); } /***/ }), /***/ "./dist/server-unpacked/VWOBuilder.js": /*!********************************************!*\ !*** ./dist/server-unpacked/VWOBuilder.js ***! \********************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __assign = this && this.__assign || function () { __assign = Object.assign || function (t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.VWOBuilder = void 0; var logger_1 = __webpack_require__(/*! ./packages/logger */ "./dist/server-unpacked/packages/logger/index.js"); var network_layer_1 = __webpack_require__(/*! ./packages/network-layer */ "./dist/server-unpacked/packages/network-layer/index.js"); var segmentation_evaluator_1 = __webpack_require__(/*! ./packages/segmentation-evaluator */ "./dist/server-unpacked/packages/segmentation-evaluator/index.js"); var storage_1 = __webpack_require__(/*! ./packages/storage */ "./dist/server-unpacked/packages/storage/index.js"); var VWOClient_1 = __webpack_require__(/*! ./VWOClient */ "./dist/server-unpacked/VWOClient.js"); var SettingsService_1 = __webpack_require__(/*! ./services/SettingsService */ "./dist/server-unpacked/services/SettingsService.js"); var log_messages_1 = __webpack_require__(/*! ./enums/log-messages */ "./dist/server-unpacked/enums/log-messages/index.js"); var DataTypeUtil_1 = __webpack_require__(/*! ./utils/DataTypeUtil */ "./dist/server-unpacked/utils/DataTypeUtil.js"); var FunctionUtil_1 = __webpack_require__(/*! ./utils/FunctionUtil */ "./dist/server-unpacked/utils/FunctionUtil.js"); var LogMessageUtil_1 = __webpack_require__(/*! ./utils/LogMessageUtil */ "./dist/server-unpacked/utils/LogMessageUtil.js"); var PromiseUtil_1 = __webpack_require__(/*! ./utils/PromiseUtil */ "./dist/server-unpacked/utils/PromiseUtil.js"); var SettingsUtil_1 = __webpack_require__(/*! ./utils/SettingsUtil */ "./dist/server-unpacked/utils/SettingsUtil.js"); var UuidUtil_1 = __webpack_require__(/*! ./utils/UuidUtil */ "./dist/server-unpacked/utils/UuidUtil.js"); var BatchEventsQueue_1 = __webpack_require__(/*! ./services/BatchEventsQueue */ "./dist/server-unpacked/services/BatchEventsQueue.js"); var BatchEventsDispatcher_1 = __webpack_require__(/*! ./utils/BatchEventsDispatcher */ "./dist/server-unpacked/utils/BatchEventsDispatcher.js"); var UsageStatsUtil_1 = __webpack_require__(/*! ./utils/UsageStatsUtil */ "./dist/server-unpacked/utils/UsageStatsUtil.js"); var VWOBuilder = /** @class */function () { function VWOBuilder(options) { this.options = options; } /** * Sets the network manager with the provided client and development mode options. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.setNetworkManager = function () { var _a, _b, _c, _d; var networkInstance = network_layer_1.NetworkManager.Instance; // Attach the network client from options networkInstance.attachClient((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.network) === null || _b === void 0 ? void 0 : _b.client, (_c = this.options) === null || _c === void 0 ? void 0 : _c.retryConfig); logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.SERVICE_INITIALIZED, { service: "Network Layer" })); // Set the development mode based on options networkInstance.getConfig().setDevelopmentMode((_d = this.options) === null || _d === void 0 ? void 0 : _d.isDevelopmentMode); return this; }; VWOBuilder.prototype.initBatching = function () { var _this = this; if (this.options.batchEventData) { if (this.settingFileManager.isGatewayServiceProvided) { logger_1.LogManager.Instance.info((0, LogMessageUtil_1.buildMessage)(log_messages_1.InfoLogMessagesEnum.GATEWAY_AND_BATCH_EVENTS_CONFIG_MISMATCH)); return this; } if ((!(0, DataTypeUtil_1.isNumber)(this.options.batchEventData.eventsPerRequest) || this.options.batchEventData.eventsPerRequest <= 0) && (!(0, DataTypeUtil_1.isNumber)(this.options.batchEventData.requestTimeInterval) || this.options.batchEventData.requestTimeInterval <= 0)) { logger_1.LogManager.Instance.error('Invalid batch events config, should be an object, eventsPerRequest should be a number greater than 0 and requestTimeInterval should be a number greater than 0'); return this; } this.batchEventsQueue = new BatchEventsQueue_1.BatchEventsQueue(Object.assign({}, this.options.batchEventData, { dispatcher: function (events, callback) { return BatchEventsDispatcher_1.BatchEventsDispatcher.dispatch({ ev: events }, callback, Object.assign({}, { a: _this.options.accountId, env: _this.options.sdkKey })); } })); this.batchEventsQueue.flushAndClearTimer.bind(this.batchEventsQueue); } return this; }; /** * Sets the segmentation evaluator with the provided segmentation options. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.setSegmentation = function () { var _a; segmentation_evaluator_1.SegmentationManager.Instance.attachEvaluator((_a = this.options) === null || _a === void 0 ? void 0 : _a.segmentation); logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.SERVICE_INITIALIZED, { service: "Segmentation Evaluator" })); return this; }; /** * Fetches settings asynchronously, ensuring no parallel fetches. * @param {boolean} [force=false] - Force fetch ignoring cache. * @returns {Promise<SettingsModel>} A promise that resolves to the fetched settings. */ VWOBuilder.prototype.fetchSettings = function (force) { var _this = this; var deferredObject = new PromiseUtil_1.Deferred(); // Check if a fetch operation is already in progress if (!this.isSettingsFetchInProgress) { this.isSettingsFetchInProgress = true; this.settingFileManager.getSettings(force).then(function (settings) { // if force is false, update original settings, if true the request is from polling and no need to update original settings if (!force) { _this.originalSettings = settings; } _this.isSettingsFetchInProgress = false; deferredObject.resolve(settings); }); return deferredObject.promise; } else { // Avoid parallel fetches by recursively calling fetchSettings return this.fetchSettings(force); } }; /** * Gets the settings, fetching them if not cached or if forced. * @param {boolean} [force=false] - Force fetch ignoring cache. * @returns {Promise<SettingsModel>} A promise that resolves to the settings. */ VWOBuilder.prototype.getSettings = function (force) { var deferredObject = new PromiseUtil_1.Deferred(); try { // Use cached settings if available and not forced to fetch if (!force && this.settings) { logger_1.LogManager.Instance.info('Using already fetched and cached settings'); deferredObject.resolve(this.settings); } else { // Fetch settings if not cached or forced this.fetchSettings(force).then(function (settings) { deferredObject.resolve(settings); }); } } catch (err) { logger_1.LogManager.Instance.error('Failed to fetch settings. Error: ' + err); deferredObject.resolve({}); } return deferredObject.promise; }; /** * Sets the storage connector based on the provided storage options. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.setStorage = function () { var _a, _b, _c, _d; if (this.options.storage) { // Attach the storage connector from options this.storage = storage_1.Storage.Instance.attachConnector(this.options.storage); } else if (typeof process.env === 'undefined' && typeof window !== 'undefined' && window.localStorage) { // eslint-disable-next-line @typescript-eslint/no-var-requires var BrowserStorageConnector = (__webpack_require__(/*! ./packages/storage/connectors/BrowserStorageConnector */ "./dist/server-unpacked/packages/storage/connectors/BrowserStorageConnector.js").BrowserStorageConnector); // Pass clientStorage config to BrowserStorageConnector this.storage = storage_1.Storage.Instance.attachConnector(new BrowserStorageConnector(__assign(__assign({}, this.options.clientStorage), { alwaysUseCachedSettings: (_a = this.options.clientStorage) === null || _a === void 0 ? void 0 : _a.alwaysUseCachedSettings, ttl: (_b = this.options.clientStorage) === null || _b === void 0 ? void 0 : _b.ttl }))); logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.SERVICE_INITIALIZED, { service: ((_d = (_c = this.options) === null || _c === void 0 ? void 0 : _c.clientStorage) === null || _d === void 0 ? void 0 : _d.provider) === sessionStorage ? "Session Storage" : "Local Storage" })); } else { // Set storage to null if no storage options provided this.storage = null; } return this; }; /** * Sets the settings manager with the provided options. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.setSettingsService = function () { this.settingFileManager = new SettingsService_1.SettingsService(this.options); return this; }; /** * Sets the logger with the provided logger options. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.setLogger = function () { this.logManager = new logger_1.LogManager(this.options.logger || {}); logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.SERVICE_INITIALIZED, { service: "Logger" })); return this; }; /** * Sets the analytics callback with the provided analytics options. * @returns {this} The instance of this builder. */ /* setAnalyticsCallback(): this { if (!isObject(this.options.analyticsEvent)) { // TODO: add logging here return this; } if (!isFunction(this.options.analyticsEvent.eventCallback)) { // TODO: add logging here return this; } if ( this.options.analyticsEvent.isBatchingSupported && !isBoolean(this.options.analyticsEvent.isBatchingSupported) ) { // TODO:- add logging here return this; } // AnalyticsEvent.Instance.attachCallback( // this.options.analyticsEvent.eventCallback, // this.options.analyticsEvent.isBatchingSupported // ); return this; } */ /** * Generates a random user ID based on the provided API key. * @returns {string} The generated random user ID. */ VWOBuilder.prototype.getRandomUserId = function () { var apiName = 'getRandomUserId'; try { logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.API_CALLED, { apiName: apiName })); return (0, UuidUtil_1.getRandomUUID)(this.options.sdkKey); } catch (err) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_THROW_ERROR, { apiName: apiName, err: err })); } }; /** * Initializes the batching with the provided batch events options. * @returns {this} The instance of this builder. */ /* initBatching(): this { if (!isObject(this.options.batchEvents)) { // TODO:- add logging here return this; } if ( isObject(this.options.batchEvents) && (!( (isNumber(this.options.batchEvents.eventsPerRequest) && this.options.batchEvents.eventsPerRequest > 0 && this.options.batchEvents.eventsPerRequest <= Constants.MAX_EVENTS_PER_REQUEST) || (isNumber(this.options.batchEvents.requestTimeInterval) && this.options.batchEvents.requestTimeInterval >= 1) ) || !isFunction(this.options.batchEvents.flushCallback)) ) { LogManager.Instance.error('Invalid batchEvents config'); // throw new Error('Invalid batchEvents config'); return this; } // BatchEventsQueue.Instance.setBatchConfig(this.options.batchEvents, this.options.sdkKey); // TODO return this; } */ /** * Initializes the polling with the provided poll interval. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.initPolling = function () { if (!this.options.pollInterval) { return this; } if (this.options.pollInterval && !(0, DataTypeUtil_1.isNumber)(this.options.pollInterval)) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.INIT_OPTIONS_INVALID, { key: 'pollInterval', correctType: 'number' })); return this; } if (this.options.pollInterval && this.options.pollInterval < 1000) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.INIT_OPTIONS_INVALID, { key: 'pollInterval', correctType: 'number' })); return this; } this.checkAndPoll(); return this; }; /** * Initializes usage statistics for the SDK. * @returns {this} The instance of this builder. */ VWOBuilder.prototype.initUsageStats = function () { if (this.options.isUsageStatsDisabled) { return this; } UsageStatsUtil_1.UsageStatsUtil.getInstance().setUsageStats(this.options); return this; }; /** * Builds a new VWOClient instance with the provided settings. * @param {SettingsModel} settings - The settings for the VWOClient. * @returns {VWOClient} The new VWOClient instance. */ VWOBuilder.prototype.build = function (settings) { this.vwoInstance = new VWOClient_1.VWOClient(settings, this.options); return this.vwoInstance; }; /** * Checks and polls for settings updates at the provided interval. */ VWOBuilder.prototype.checkAndPoll = function () { var _this = this; var pollingInterval = this.options.pollInterval; setInterval(function () { _this.getSettings(true).then(function (latestSettings) { var lastSettings = JSON.stringify(_this.originalSettings); var stringifiedLatestSettings = JSON.stringify(latestSettings); if (stringifiedLatestSettings !== lastSettings) { _this.originalSettings = latestSettings; var clonedSettings = (0, FunctionUtil_1.cloneObject)(latestSettings); logger_1.LogManager.Instance.info(log_messages_1.InfoLogMessagesEnum.POLLING_SET_SETTINGS); (0, SettingsUtil_1.setSettingsAndAddCampaignsToRules)(clonedSettings, _this.vwoInstance); } else { logger_1.LogManager.Instance.info(log_messages_1.InfoLogMessagesEnum.POLLING_NO_CHANGE_IN_SETTINGS); } }).catch(function () { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.POLLING_FETCH_SETTINGS_FAILED); }); }, pollingInterval); }; return VWOBuilder; }(); exports.VWOBuilder = VWOBuilder; /***/ }), /***/ "./dist/server-unpacked/VWOClient.js": /*!*******************************************!*\ !*** ./dist/server-unpacked/VWOClient.js ***! \*******************************************/ /***/ (function(__unused_webpack_module, exports, __webpack_require__) { var __awaiter = this && this.__awaiter || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = this && this.__generator || function (thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.VWOClient = void 0; /** * 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 logger_1 = __webpack_require__(/*! ./packages/logger */ "./dist/server-unpacked/packages/logger/index.js"); var GetFlag_1 = __webpack_require__(/*! ./api/GetFlag */ "./dist/server-unpacked/api/GetFlag.js"); var SetAttribute_1 = __webpack_require__(/*! ./api/SetAttribute */ "./dist/server-unpacked/api/SetAttribute.js"); var TrackEvent_1 = __webpack_require__(/*! ./api/TrackEvent */ "./dist/server-unpacked/api/TrackEvent.js"); var log_messages_1 = __webpack_require__(/*! ./enums/log-messages */ "./dist/server-unpacked/enums/log-messages/index.js"); var BatchEventsQueue_1 = __webpack_require__(/*! ./services/BatchEventsQueue */ "./dist/server-unpacked/services/BatchEventsQueue.js"); var SettingsSchemaValidation_1 = __webpack_require__(/*! ./models/schemas/SettingsSchemaValidation */ "./dist/server-unpacked/models/schemas/SettingsSchemaValidation.js"); var ContextModel_1 = __webpack_require__(/*! ./models/user/ContextModel */ "./dist/server-unpacked/models/user/ContextModel.js"); var HooksService_1 = __webpack_require__(/*! ./services/HooksService */ "./dist/server-unpacked/services/HooksService.js"); var UrlUtil_1 = __webpack_require__(/*! ./utils/UrlUtil */ "./dist/server-unpacked/utils/UrlUtil.js"); var DataTypeUtil_1 = __webpack_require__(/*! ./utils/DataTypeUtil */ "./dist/server-unpacked/utils/DataTypeUtil.js"); var LogMessageUtil_1 = __webpack_require__(/*! ./utils/LogMessageUtil */ "./dist/server-unpacked/utils/LogMessageUtil.js"); var PromiseUtil_1 = __webpack_require__(/*! ./utils/PromiseUtil */ "./dist/server-unpacked/utils/PromiseUtil.js"); var SettingsUtil_1 = __webpack_require__(/*! ./utils/SettingsUtil */ "./dist/server-unpacked/utils/SettingsUtil.js"); var VariationModel_1 = __webpack_require__(/*! ./models/campaign/VariationModel */ "./dist/server-unpacked/models/campaign/VariationModel.js"); var NetworkUtil_1 = __webpack_require__(/*! ./utils/NetworkUtil */ "./dist/server-unpacked/utils/NetworkUtil.js"); var SettingsService_1 = __webpack_require__(/*! ./services/SettingsService */ "./dist/server-unpacked/services/SettingsService.js"); var ApiEnum_1 = __webpack_require__(/*! ./enums/ApiEnum */ "./dist/server-unpacked/enums/ApiEnum.js"); var VWOClient = /** @class */function () { function VWOClient(settings, options) { this.options = options; (0, SettingsUtil_1.setSettingsAndAddCampaignsToRules)(settings, this); UrlUtil_1.UrlUtil.init({ collectionPrefix: this.settings.getCollectionPrefix() }); (0, NetworkUtil_1.setShouldWaitForTrackingCalls)(this.options.shouldWaitForTrackingCalls || false); logger_1.LogManager.Instance.info(log_messages_1.InfoLogMessagesEnum.CLIENT_INITIALIZED); this.vwoClientInstance = this; return this; } /** * Retrieves the value of a feature flag for a given feature key and context. * This method validates the feature key and context, ensures the settings are valid, and then uses the FlagApi to get the flag value. * * @param {string} featureKey - The key of the feature to retrieve. * @param {ContextModel} context - The context in which the feature flag is being retrieved, must include a valid user ID. * @returns {Promise<Flag>} - A promise that resolves to the feature flag value. */ VWOClient.prototype.getFlag = function (featureKey, context) { var apiName = ApiEnum_1.ApiEnum.GET_FLAG; var deferredObject = new PromiseUtil_1.Deferred(); var errorReturnSchema = new GetFlag_1.Flag(false, new VariationModel_1.VariationModel()); try { var hooksService = new HooksService_1.default(this.options); logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.API_CALLED, { apiName: apiName })); // Validate featureKey is a string if (!(0, DataTypeUtil_1.isString)(featureKey)) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_INVALID_PARAM, { apiName: apiName, key: 'featureKey', type: (0, DataTypeUtil_1.getType)(featureKey), correctType: 'string' })); throw new TypeError('TypeError: featureKey should be a string'); } // Validate settings are loaded and valid if (!new SettingsSchemaValidation_1.SettingsSchema().isSettingsValid(this.originalSettings)) { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.API_SETTING_INVALID); throw new Error('TypeError: Invalid Settings'); } // Validate user ID is present in context if (!context || !context.id) { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.API_CONTEXT_INVALID); throw new TypeError('TypeError: Invalid context'); } var contextModel = new ContextModel_1.ContextModel().modelFromDictionary(context); GetFlag_1.FlagApi.get(featureKey, this.settings, contextModel, hooksService).then(function (data) { deferredObject.resolve(data); }).catch(function () { deferredObject.resolve(errorReturnSchema); }); } catch (err) { logger_1.LogManager.Instance.info((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_THROW_ERROR, { apiName: apiName, err: err })); deferredObject.resolve(errorReturnSchema); } return deferredObject.promise; }; /** * Tracks an event with specified properties and context. * This method validates the types of the inputs and ensures the settings and user context are valid before proceeding. * * @param {string} eventName - The name of the event to track. * @param {ContextModel} context - The context in which the event is being tracked, must include a valid user ID. * @param {Record<string, dynamic>} eventProperties - The properties associated with the event. * @returns {Promise<Record<string, boolean>>} - A promise that resolves to the result of the tracking operation. */ VWOClient.prototype.trackEvent = function (eventName, context, eventProperties) { var _a; if (eventProperties === void 0) { eventProperties = {}; } var apiName = ApiEnum_1.ApiEnum.TRACK_EVENT; var deferredObject = new PromiseUtil_1.Deferred(); try { var hooksService = new HooksService_1.default(this.options); // Log the API call logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.API_CALLED, { apiName: apiName })); // Validate eventName is a string if (!(0, DataTypeUtil_1.isString)(eventName)) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_INVALID_PARAM, { apiName: apiName, key: 'eventName', type: (0, DataTypeUtil_1.getType)(eventName), correctType: 'string' })); throw new TypeError('TypeError: Event-name should be a string'); } // Validate eventProperties is an object if (!(0, DataTypeUtil_1.isObject)(eventProperties)) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_INVALID_PARAM, { apiName: apiName, key: 'eventProperties', type: (0, DataTypeUtil_1.getType)(eventProperties), correctType: 'object' })); throw new TypeError('TypeError: eventProperties should be an object'); } // Validate settings are loaded and valid if (!new SettingsSchemaValidation_1.SettingsSchema().isSettingsValid(this.originalSettings)) { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.API_SETTING_INVALID); throw new Error('TypeError: Invalid Settings'); } // Validate user ID is present in context if (!context || !context.id) { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.API_CONTEXT_INVALID); throw new TypeError('TypeError: Invalid context'); } var contextModel = new ContextModel_1.ContextModel().modelFromDictionary(context); // Proceed with tracking the event new TrackEvent_1.TrackApi().track(this.settings, eventName, contextModel, eventProperties, hooksService).then(function (data) { deferredObject.resolve(data); }).catch(function () { var _a; deferredObject.resolve((_a = {}, _a[eventName] = false, _a)); }); } catch (err) { // Log any errors encountered during the operation logger_1.LogManager.Instance.info((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_THROW_ERROR, { apiName: apiName, err: err })); deferredObject.resolve((_a = {}, _a[eventName] = false, _a)); } return deferredObject.promise; }; /** * Sets an attribute or multiple attributes for a user in the provided context. * This method validates the types of the inputs before proceeding with the API call. * There are two cases handled: * 1. When attributes are passed as a map (key-value pairs). * 2. When a single attribute (key-value) is passed. * * @param {string | Record<string, boolean | string | number>} attributeOrAttributes - Either a single attribute key (string) and value (boolean | string | number), * or a map of attributes with keys and values (boolean | string | number). * @param {boolean | string | number | Record<string, any>} [attributeValueOrContext] - The value for the attribute in case of a single attribute, or the context when multiple attributes are passed. * @param {Record<string, any>} [context] - The context which must include a valid user ID. This is required if multiple attributes are passed. */ VWOClient.prototype.setAttribute = function (attributeOrAttributes, attributeValueOrContext, context) { return __awaiter(this, void 0, void 0, function () { var apiName, attributes, contextModel, attributeKey, attributeValue, contextModel, attributeMap, err_1; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: apiName = ApiEnum_1.ApiEnum.SET_ATTRIBUTE; _b.label = 1; case 1: _b.trys.push([1, 6,, 7]); if (!(0, DataTypeUtil_1.isObject)(attributeOrAttributes)) return [3 /*break*/, 3]; // Log the API call logger_1.LogManager.Instance.debug((0, LogMessageUtil_1.buildMessage)(log_messages_1.DebugLogMessagesEnum.API_CALLED, { apiName: apiName })); if (Object.entries(attributeOrAttributes).length < 1) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)('Attributes map must contain atleast 1 key-value pair', { apiName: apiName, key: 'attributes', type: (0, DataTypeUtil_1.getType)(attributeOrAttributes), correctType: 'object' })); throw new TypeError('TypeError: Attributes should be an object containing atleast 1 key-value pair'); } attributes = attributeOrAttributes; // Validate attributes is an object if (!(0, DataTypeUtil_1.isObject)(attributes)) { throw new TypeError('TypeError: attributes should be an object containing key-value pairs'); } // Validate that each attribute value is of a supported type Object.entries(attributes).forEach(function (_a) { var key = _a[0], value = _a[1]; if (typeof value !== 'boolean' && typeof value !== 'string' && typeof value !== 'number') { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_INVALID_PARAM, { apiName: apiName, key: key, type: (0, DataTypeUtil_1.getType)(value), correctType: ' boolean, string or number' })); throw new TypeError("Invalid attribute type for key \"".concat(key, "\". Expected boolean, string or number, but got ").concat((0, DataTypeUtil_1.getType)(value))); } // Reject arrays and objects explicitly if (Array.isArray(value) || typeof value === 'object' && value !== null) { logger_1.LogManager.Instance.error((0, LogMessageUtil_1.buildMessage)(log_messages_1.ErrorLogMessagesEnum.API_INVALID_PARAM, { apiName: apiName, key: key, type: (0, DataTypeUtil_1.getType)(value), correctType: ' boolean | string | number | null' })); throw new TypeError("Invalid attribute value for key \"".concat(key, "\". Arrays and objects are not supported.")); } }); // If we have only two arguments (attributeMap and context) if (!context && attributeValueOrContext) { context = attributeValueOrContext; // Assign context explicitly } // Validate user ID is present in context if (!context || !context.id) { logger_1.LogManager.Instance.error(log_messages_1.ErrorLogMessagesEnum.API_CONTEXT_INVALID); } contextModel = new ContextMod