ibm-appconfiguration-js-client-sdk
Version:
IBM Cloud App Configuration JavaScript Client SDK
209 lines (208 loc) • 9.55 kB
JavaScript
"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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var Constants = __importStar(require("../utils/constants"));
var metering_1 = __importDefault(require("../utils/metering"));
var Cache_1 = require("./Cache");
var PropertySegmentRule_1 = __importDefault(require("./PropertySegmentRule"));
var logger_1 = require("../utils/logger");
var logger = new logger_1.Logger(Constants.APP_CONFIGURATION);
var Property = /** @class */ (function () {
function Property(_a) {
var name = _a.name, property_id = _a.property_id, type = _a.type, _b = _a.format, format = _b === void 0 ? undefined : _b, value = _a.value, segment_rules = _a.segment_rules;
this.name = name;
this.property_id = property_id;
this.type = type;
this.format = format; // will be undefined for boolean & numeric datatypes
this.value = value;
this.segment_rules = [];
for (var _i = 0, segment_rules_1 = segment_rules; _i < segment_rules_1.length; _i++) {
var element = segment_rules_1[_i];
this.segment_rules.push(new PropertySegmentRule_1.default(element));
}
}
/**
* Get the Property name.
*
* @return {*} {string} The Property name.
* @memberof Property
*/
Property.prototype.getPropertyName = function () {
return this.name;
};
/**
* Get the Property id.
*
* @return {*} {string} The Property Id.
* @memberof Property
*/
Property.prototype.getPropertyId = function () {
return this.property_id;
};
/**
* Get the Property data type.
*
* @return {*} {string} string named BOOLEAN/STRING/NUMERIC.
* @memberof Property
*/
Property.prototype.getPropertyDataType = function () {
return this.type;
};
/**
* Get the Property data format.
* Applicable only for STRING datatype property.
*
* @return {*} {(string | undefined)} string named TEXT/JSON/YAML.
* @memberof Property
*/
Property.prototype.getPropertyDataFormat = function () {
// Format will be `undefined` for Boolean & Numeric properties
// If the Format is null or undefined for a String type, we default it to TEXT
if (!(this.format) && this.type === 'STRING') {
this.format = 'TEXT';
}
return this.format;
};
/**
* Get the evaluated value of the property.
*
* @param {string} entityId - Id of the Entity.
* This will be a string identifier related to the Entity against which the property is evaluated.
* For example, an entity might be an instance of an app that runs on a mobile device, a microservice that runs on the cloud, or a component of infrastructure that runs that microservice.
* For any entity to interact with App Configuration, it must provide a unique entity ID.
*
* @param {{ [x: string]: any; }} entityAttributes - A JSON object consisting of the attribute name and their values that defines the specified entity.
* This is an optional parameter if the property is not configured with any targeting definition. If the targeting is configured, then entityAttributes should be provided for the rule evaluation.
* An attribute is a parameter that is used to define a segment. The SDK uses the attribute values to determine if the
* specified entity satisfies the targeting rules, and returns the appropriate property value.
*
* @return {*} {*} Returns the default property value or its overridden value based on the evaluation.
* The data type of returned value matches that of property.
* @memberof Property
*/
Property.prototype.getCurrentValue = function (entityId, entityAttributes) {
if (entityAttributes === void 0) { entityAttributes = {}; }
if (!entityId) {
logger.log(''.concat('Property evaluation: ', Constants.INVALID_ENTITY_ID, ' getCurrentValue'));
return null;
}
return this.propertyEvaluation(entityId, entityAttributes);
};
Property.prototype.propertyEvaluation = function (entityId, entityAttributes) {
var evaluationResult = {
evaluated_segment_id: Constants.DEFAULT_SEGMENT_ID,
value: null,
};
try {
// check whether the property is configured with any targeting definition and then check whether the user has passed an valid entityAttributes JSON before we evaluate
if (this.segment_rules.length > 0 && Object.keys(entityAttributes).length > 0) {
var rulesMap = this.parseRules(this.segment_rules);
evaluationResult = this.evaluateRules(rulesMap, entityId, entityAttributes);
return evaluationResult.value;
}
return this.value;
}
finally {
metering_1.default.getInstance().addMetering(entityId, evaluationResult.evaluated_segment_id, null, this.property_id);
}
};
Property.prototype.parseRules = function (segmentRules) {
var rulesMap = {};
segmentRules.forEach(function (rules) {
rulesMap[rules.order] = rules;
});
return rulesMap;
};
Property.prototype.evaluateRules = function (rulesMap, _entityId, entityAttributes) {
var resultDict = {
evaluated_segment_id: Constants.DEFAULT_SEGMENT_ID,
value: null,
};
try {
// for each rules in the targeting
for (var index = 1; index <= Object.keys(rulesMap).length; index += 1) {
var segmentRule = rulesMap[index];
if (segmentRule.rules.length > 0) {
for (var _i = 0, _a = segmentRule.rules; _i < _a.length; _i++) {
var level = _a[_i];
var segments = level.segments;
if (segments.length > 0) {
// for each segment in a rule
for (var _b = 0, segments_1 = segments; _b < segments_1.length; _b++) {
var innerLevel = segments_1[_b];
var segmentId = innerLevel;
// check whether the entityAttributes satifies all the rules of that segment
if (this.evaluateSegment(segmentId, entityAttributes)) {
resultDict.evaluated_segment_id = segmentId;
{
if (segmentRule.value === Constants.DEFAULT_PROPERTY_VALUE) {
resultDict.value = this.value;
}
else {
resultDict.value = segmentRule.value;
}
}
return resultDict;
}
}
}
}
}
}
}
catch (e) {
console.error(''.concat(Constants.APP_CONFIGURATION, 'PropertyRuleEvaluation', e.message));
}
resultDict.value = this.value;
return resultDict;
};
Property.prototype.evaluateSegment = function (segmentId, entityAttributes) {
var segment = (0, Cache_1.getCacheInstance)().segments;
if (Object.prototype.hasOwnProperty.call(segment, segmentId)) {
return segment[segmentId].evaluateRule(entityAttributes);
}
return false;
};
return Property;
}());
exports.default = Property;