UNPKG

ibm-appconfiguration-js-client-sdk

Version:
281 lines (280 loc) 14.3 kB
"use strict"; /** * Copyright 2022 IBM Corp. All Rights Reserved. * * 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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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; return g = { next: verb(0), "throw": verb(1), "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 }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var Cache_1 = require("./models/Cache"); var Feature_1 = __importDefault(require("./models/Feature")); var Property_1 = __importDefault(require("./models/Property")); var Segment_1 = __importDefault(require("./models/Segment")); var eventsource_1 = require("./polyfill/eventsource"); var Constants = __importStar(require("./utils/constants")); var events_handler_1 = __importDefault(require("./utils/events-handler")); var metering_1 = __importDefault(require("./utils/metering")); var urlbuilder_1 = __importDefault(require("./utils/urlbuilder")); var logger_1 = require("./utils/logger"); var rollout_1 = require("./utils/rollout"); var apimanager_1 = require("./utils/apimanager"); var urlBuilder = urlbuilder_1.default.getInstance(); var metering = metering_1.default.getInstance(); var logger = new logger_1.Logger(Constants.APP_CONFIGURATION); var ConfigurationHandler = /** @class */ (function () { function ConfigurationHandler() { this.isRestrictedNetwork = false; this.setContextConfigFetched = false; } ConfigurationHandler.prototype.init = function (region, guid, apikey, overrideServiceUrl, isRestrictedNetwork) { var _a; this.region = region; this.guid = guid; this.apikey = apikey; this.overrideServiceUrl = overrideServiceUrl; this.isRestrictedNetwork = isRestrictedNetwork; if ((_a = window === null || window === void 0 ? void 0 : window.IBM_CLOUD_APP_CONFIG) === null || _a === void 0 ? void 0 : _a.isClientInRestrictedNetwork) { this.isRestrictedNetwork = true; } }; ConfigurationHandler.prototype.setContext = function (collectionId, environmentId) { return __awaiter(this, void 0, void 0, function () { var config; return __generator(this, function (_a) { switch (_a.label) { case 0: urlBuilder.init({ region: this.region, guid: this.guid, apikey: this.apikey, collectionId: collectionId, environmentId: environmentId, overrideServiceUrl: this.overrideServiceUrl, isRestrictedNetwork: this.isRestrictedNetwork, }); metering.init(collectionId, environmentId); rollout_1.PhaseScheduler.onPhaseCallback = function () { events_handler_1.default.emit(Constants.CONFIGURATION_UPDATE_EVENT); }; if (!this.isRestrictedNetwork) return [3 /*break*/, 2]; return [4 /*yield*/, (0, apimanager_1.retryableGetConfig)()]; case 1: config = _a.sent(); this.saveInCache(config); this.setContextConfigFetched = true; this.connectEventSource().catch(function (reason) { return Promise.reject(reason); }); return [3 /*break*/, 4]; case 2: return [4 /*yield*/, this.connectEventSource()]; case 3: _a.sent(); _a.label = 4; case 4: return [2 /*return*/]; } }); }); }; ConfigurationHandler.prototype.saveInCache = function (data) { rollout_1.PhaseScheduler.reset(); var _featureMap = {}; var _rolloutConfigMap = {}; if (Object.keys(data.environments[0].features).length) { var featuresList = data.environments[0].features; featuresList.forEach(function (feature) { _featureMap[feature.feature_id] = new Feature_1.default(feature); // Parse feature-level progressive rollout if (feature.rollout_configuration) { var rolloutMap = (0, rollout_1.parseRolloutConfigurationPhases)(feature.rollout_configuration); if (rolloutMap) { _rolloutConfigMap[feature.feature_id] = rolloutMap; } else { logger.log('Error parsing feature rollout configuration'); } } // Parse segment-level progressive rollout if (feature.segment_rules && feature.segment_rules.length > 0) { for (var _i = 0, _a = feature.segment_rules; _i < _a.length; _i++) { var segmentRule = _a[_i]; if (segmentRule.rollout_configuration) { var rolloutMap = (0, rollout_1.parseRolloutConfigurationPhases)(segmentRule.rollout_configuration); if (rolloutMap) { var key = feature.feature_id + Constants.DELIMITER + (segmentRule.rule_id || ''); _rolloutConfigMap[key] = rolloutMap; } else { logger.log('Error parsing segment rule rollout configuration'); } } } } }); } var _propertyMap = {}; if (Object.keys(data.environments[0].properties).length) { var propertiesList = data.environments[0].properties; propertiesList.forEach(function (property) { _propertyMap[property.property_id] = new Property_1.default(property); }); } var _segmentMap = {}; if (Object.keys(data.segments).length) { var segments = data.segments; segments.forEach(function (segment) { _segmentMap[segment.segment_id] = new Segment_1.default(segment); }); } (0, Cache_1.setCache)(_featureMap, _propertyMap, _segmentMap, _rolloutConfigMap); }; ConfigurationHandler.prototype.connectEventSource = function () { var _this = this; var url = urlBuilder.getEventSourceUrl(); var headers = urlBuilder.getEventSourceHeaders(); var source = new eventsource_1.EventSourcePolyfill(url, headers); if (this.isRestrictedNetwork) { source.addEventListener('SSEEvent_update', function (_) { logger.log("Update event received. Fetching data from server..."); (0, apimanager_1.retryableGetConfig)().then(function (config) { _this.saveInCache(config); events_handler_1.default.emit(Constants.CONFIGURATION_UPDATE_EVENT); }); }); } else { source.addEventListener('SSEConfig_payload', function (event) { var eventData = JSON.parse(event.data); logger.log("Update event received."); _this.saveInCache(eventData); events_handler_1.default.emit(Constants.CONFIGURATION_UPDATE_EVENT); }); } return new Promise(function (resolve, reject) { source.addEventListener('error', function (err) { reject(err); }); source.addEventListener('Registration', function (event) { if (_this.isRestrictedNetwork) { if (_this.setContextConfigFetched) { _this.setContextConfigFetched = false; events_handler_1.default.emit(Constants.REGISTRATION_EVENT); logger.log("Client registration complete."); resolve(); } else { (0, apimanager_1.retryableGetConfig)().then(function (config) { _this.saveInCache(config); events_handler_1.default.emit(Constants.REGISTRATION_EVENT); logger.log("Client registration complete."); resolve(); }); } } else { var eventData = JSON.parse(event.data); _this.saveInCache(eventData); events_handler_1.default.emit(Constants.REGISTRATION_EVENT); logger.log("Client registration complete."); resolve(); } }); }); }; ConfigurationHandler.prototype.getFeature = function (featureId) { if (Object.prototype.hasOwnProperty.call((0, Cache_1.getCacheInstance)().features, featureId)) { return (0, Cache_1.getCacheInstance)().features[featureId]; } throw new Error(''.concat(Constants.APP_CONFIGURATION, 'Invalid feature flag id: ', featureId)); }; ConfigurationHandler.prototype.getFeatures = function () { return (0, Cache_1.getCacheInstance)().features; }; ConfigurationHandler.prototype.getProperty = function (propertyId) { if (Object.prototype.hasOwnProperty.call((0, Cache_1.getCacheInstance)().properties, propertyId)) { return (0, Cache_1.getCacheInstance)().properties[propertyId]; } throw new Error(''.concat(Constants.APP_CONFIGURATION, 'Invalid property id: ', propertyId)); }; ConfigurationHandler.prototype.getProperties = function () { return (0, Cache_1.getCacheInstance)().properties; }; ConfigurationHandler.getInstance = function () { if (!ConfigurationHandler.instance) { ConfigurationHandler.instance = new ConfigurationHandler(); } return ConfigurationHandler.instance; }; return ConfigurationHandler; }()); exports.default = ConfigurationHandler;