@sap-devx/feature-toggle-node
Advanced tools
Comparing version 1.0.10 to 1.0.11
export declare const ENV_FT_SERVER_ENDPOINT_NAME = "FT_SERVER_ENDPOINT"; | ||
export declare const ENV_REFRESH_INTERVAL_NAME = "FT_CLIENT_REFRESH_INTERVAL"; | ||
export declare const ENV_FT_TOKEN = "FT_TOKEN"; | ||
@@ -4,0 +3,0 @@ export interface ServerArgs { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getServerArgs = exports.ENV_FT_TOKEN = exports.ENV_REFRESH_INTERVAL_NAME = exports.ENV_FT_SERVER_ENDPOINT_NAME = void 0; | ||
exports.getServerArgs = exports.ENV_FT_TOKEN = exports.ENV_FT_SERVER_ENDPOINT_NAME = void 0; | ||
const logger_1 = require("./logger"); | ||
const utils_1 = require("./utils"); | ||
const parse_duration_1 = require("parse-duration"); | ||
exports.ENV_FT_SERVER_ENDPOINT_NAME = "FT_SERVER_ENDPOINT"; | ||
exports.ENV_REFRESH_INTERVAL_NAME = "FT_CLIENT_REFRESH_INTERVAL"; | ||
exports.ENV_FT_TOKEN = "FT_TOKEN"; | ||
const DEFAULT_REFRESH_INTERVAL = 10000; //10 sec | ||
// get featureToggle server url and client refresh interval from environment variables | ||
const MILLISECONDS_IN_MINUTE = 60000; | ||
const REFRESH_INTERVAL = MILLISECONDS_IN_MINUTE * 15; //15 minutes | ||
// get featureToggle server url from environment variables | ||
function getServerArgs() { | ||
//get feature server endpoint from env variable | ||
let endpoint = utils_1.getEnv(exports.ENV_FT_SERVER_ENDPOINT_NAME, "Feature toggle server endpoint (FT_SERVER_ENDPOINT) was NOT found in the environment variables."); | ||
// add /api/ to url. handles url with trailing slash and without | ||
endpoint = endpoint.replace(/\/?$/, "/api/"); | ||
//get refresh interval | ||
const intervalEnv = process.env[exports.ENV_REFRESH_INTERVAL_NAME]; | ||
let interval; | ||
// do not parse undefined, empty... | ||
if (intervalEnv) { | ||
interval = parse_duration_1.default(intervalEnv); | ||
} | ||
// parse parseDuration result | ||
if (!interval) { | ||
interval = DEFAULT_REFRESH_INTERVAL; | ||
logger_1.log(`[ERROR] client refresh interval not set or in incorrect pattern, using the default interval: ${DEFAULT_REFRESH_INTERVAL}`); | ||
} | ||
logger_1.log(`client refresh interval is: ${interval}`); | ||
return { ftServerEndPoint: endpoint, ftServerInterval: interval, ftServerToken: process.env[exports.ENV_FT_TOKEN] }; | ||
logger_1.log(`client refresh interval is: ${REFRESH_INTERVAL}`); | ||
return { ftServerEndPoint: endpoint, ftServerInterval: REFRESH_INTERVAL, ftServerToken: process.env[exports.ENV_FT_TOKEN] }; | ||
} | ||
exports.getServerArgs = getServerArgs; | ||
//# sourceMappingURL=server_arguments.js.map |
import { Unleash } from "unleash-client"; | ||
export interface InitializeAttempt { | ||
numAttempt: number; | ||
timeAttempt: number; | ||
isBlocked: boolean; | ||
} | ||
export declare function handleUnauthorisedCalls(extensionName: string, initializeAttemptMap: Map<string, InitializeAttempt>): void; | ||
export declare function getUnleashClientFromMap(extensionName: string, unleashClientMap: Map<string, Unleash>): Promise<Unleash>; | ||
export declare function getUnleashClient(extensionName: string): Promise<Unleash>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getUnleashClient = exports.getUnleashClientFromMap = void 0; | ||
exports.getUnleashClient = exports.getUnleashClientFromMap = exports.handleUnauthorisedCalls = void 0; | ||
const ServerArgs = require("./server_arguments"); | ||
@@ -12,2 +12,28 @@ const unleash_client_wrapper_1 = require("./unleash_client_wrapper"); | ||
const unleashClientMap = new Map(); | ||
// map key = extensionName | ||
// map value = info regarding attempts to establish unleash client | ||
const initializeAttemptMap = new Map(); | ||
const limitNumber = 2; | ||
function handleUnauthorisedError(extensionName) { | ||
var _a; | ||
let num = (_a = initializeAttemptMap.get(extensionName)) === null || _a === void 0 ? void 0 : _a.numAttempt; | ||
num = (num || 0) + 1; | ||
const isInitBlocked = num == limitNumber; | ||
initializeAttemptMap.set(extensionName, { numAttempt: num, timeAttempt: Date.now(), isBlocked: isInitBlocked }); | ||
} | ||
// block calls for client initialization while in block time period. | ||
function handleUnauthorisedCalls(extensionName, initializeAttemptMap) { | ||
const initializationInfo = initializeAttemptMap.get(extensionName); | ||
if (initializationInfo === null || initializationInfo === void 0 ? void 0 : initializationInfo.isBlocked) { | ||
const lastAttemptTime = initializationInfo.timeAttempt; | ||
const timeDifference = Math.abs((Date.now() - lastAttemptTime) / (1000 * 60)); | ||
const blockPeriod = Math.floor(Math.random() * 3) + 9; //10 min (+-1min) | ||
if (timeDifference < blockPeriod) { | ||
throw new Error(`The limit of attempts to create unleash client for ${extensionName} has been reached. Attempts will be blocked for the next 10 min.`); | ||
} | ||
// block period is over | ||
initializeAttemptMap.set(extensionName, { numAttempt: 0, timeAttempt: 0, isBlocked: false }); | ||
} | ||
} | ||
exports.handleUnauthorisedCalls = handleUnauthorisedCalls; | ||
async function createNewUnleashClient(extensionName, unleashClientMap) { | ||
@@ -18,3 +44,6 @@ //get server env arguments | ||
const appStudioMultiStrategy = new appStudioMultiStrategy_1.AppStudioMultiStrategy(); | ||
const client = await unleash_client_wrapper_1.initializeUnleashClient(extensionName, serverArgs, [appStudioMultiStrategy]); | ||
const client = await unleash_client_wrapper_1.initializeUnleashClient(extensionName, serverArgs, [appStudioMultiStrategy]).catch((err) => { | ||
handleUnauthorisedError(extensionName); | ||
throw err; | ||
}); | ||
appStudioStrategies_1.registerStrategies(appStudioMultiStrategy); | ||
@@ -31,2 +60,3 @@ //add the client to the map | ||
} | ||
handleUnauthorisedCalls(extensionName, initializeAttemptMap); | ||
// The client does NOT exist in the map -> create a new client | ||
@@ -33,0 +63,0 @@ return createNewUnleashClient(extensionName, unleashClientMap); |
@@ -36,2 +36,3 @@ "use strict"; | ||
strategies: customStrategies, | ||
disableMetrics: true, | ||
}; | ||
@@ -38,0 +39,0 @@ if (serverArgs.ftServerToken) { |
{ | ||
"name": "@sap-devx/feature-toggle-node", | ||
"version": "1.0.10", | ||
"version": "1.0.11", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/api.js", |
@@ -49,3 +49,2 @@ [![CircleCI](https://circleci.com/gh/SAP/feature-toggle-node.svg?style=svg)](https://circleci.com/gh/SAP/feature-toggle-node) | ||
- `FT_TOKEN` - Value of the feature toggle server API token (optional) | ||
- `FT_CLIENT_REFRESH_INTERVAL` - Feature toggle client refresh interval (optional, default value: 10s) | ||
- `SHOW_LOG` - If true, displays console logs (optional) | ||
@@ -58,3 +57,2 @@ | ||
"USER_NAME": "user@hotmail.com", | ||
"FT_CLIENT_REFRESH_INTERVAL": "6s", | ||
"TENANT_ID" : "b5c05535-9495-4050-9d68-4356d0d34136", | ||
@@ -61,0 +59,0 @@ "TENANT_NAME": "cfsubaccount" // subaccount, |
import { log } from "./logger"; | ||
import { getEnv } from "./utils"; | ||
import parseDuration from "parse-duration"; | ||
export const ENV_FT_SERVER_ENDPOINT_NAME = "FT_SERVER_ENDPOINT"; | ||
export const ENV_REFRESH_INTERVAL_NAME = "FT_CLIENT_REFRESH_INTERVAL"; | ||
export const ENV_FT_TOKEN = "FT_TOKEN"; | ||
const DEFAULT_REFRESH_INTERVAL = 10000; //10 sec | ||
const MILLISECONDS_IN_MINUTE = 60000; | ||
const REFRESH_INTERVAL = MILLISECONDS_IN_MINUTE * 15; //15 minutes | ||
@@ -16,24 +15,10 @@ export interface ServerArgs { | ||
// get featureToggle server url and client refresh interval from environment variables | ||
// get featureToggle server url from environment variables | ||
export function getServerArgs(): ServerArgs { | ||
//get feature server endpoint from env variable | ||
let endpoint = getEnv(ENV_FT_SERVER_ENDPOINT_NAME, "Feature toggle server endpoint (FT_SERVER_ENDPOINT) was NOT found in the environment variables."); | ||
// add /api/ to url. handles url with trailing slash and without | ||
endpoint = endpoint.replace(/\/?$/, "/api/"); | ||
log(`client refresh interval is: ${REFRESH_INTERVAL}`); | ||
//get refresh interval | ||
const intervalEnv = process.env[ENV_REFRESH_INTERVAL_NAME]; | ||
let interval; | ||
// do not parse undefined, empty... | ||
if (intervalEnv) { | ||
interval = parseDuration(intervalEnv); | ||
} | ||
// parse parseDuration result | ||
if (!interval) { | ||
interval = DEFAULT_REFRESH_INTERVAL; | ||
log(`[ERROR] client refresh interval not set or in incorrect pattern, using the default interval: ${DEFAULT_REFRESH_INTERVAL}`); | ||
} | ||
log(`client refresh interval is: ${interval}`); | ||
return { ftServerEndPoint: endpoint, ftServerInterval: interval, ftServerToken: process.env[ENV_FT_TOKEN] }; | ||
return { ftServerEndPoint: endpoint, ftServerInterval: REFRESH_INTERVAL, ftServerToken: process.env[ENV_FT_TOKEN] }; | ||
} |
@@ -12,2 +12,35 @@ import { Unleash } from "unleash-client"; | ||
export interface InitializeAttempt { | ||
numAttempt: number; | ||
timeAttempt: number; | ||
isBlocked: boolean; | ||
} | ||
// map key = extensionName | ||
// map value = info regarding attempts to establish unleash client | ||
const initializeAttemptMap = new Map<string, InitializeAttempt>(); | ||
const limitNumber = 2; | ||
function handleUnauthorisedError(extensionName: string): void { | ||
let num = initializeAttemptMap.get(extensionName)?.numAttempt; | ||
num = (num || 0) + 1; | ||
const isInitBlocked = num == limitNumber; | ||
initializeAttemptMap.set(extensionName, { numAttempt: num, timeAttempt: Date.now(), isBlocked: isInitBlocked }); | ||
} | ||
// block calls for client initialization while in block time period. | ||
export function handleUnauthorisedCalls(extensionName: string, initializeAttemptMap: Map<string, InitializeAttempt>): void { | ||
const initializationInfo = initializeAttemptMap.get(extensionName); | ||
if (initializationInfo?.isBlocked) { | ||
const lastAttemptTime = initializationInfo.timeAttempt; | ||
const timeDifference = Math.abs((Date.now() - lastAttemptTime) / (1000 * 60)); | ||
const blockPeriod = Math.floor(Math.random() * 3) + 9; //10 min (+-1min) | ||
if (timeDifference < blockPeriod) { | ||
throw new Error(`The limit of attempts to create unleash client for ${extensionName} has been reached. Attempts will be blocked for the next 10 min.`); | ||
} | ||
// block period is over | ||
initializeAttemptMap.set(extensionName, { numAttempt: 0, timeAttempt: 0, isBlocked: false }); | ||
} | ||
} | ||
async function createNewUnleashClient(extensionName: string, unleashClientMap: Map<string, Unleash>): Promise<Unleash> { | ||
@@ -19,3 +52,8 @@ //get server env arguments | ||
const appStudioMultiStrategy = new AppStudioMultiStrategy(); | ||
const client = await initializeUnleashClient(extensionName, serverArgs, [appStudioMultiStrategy]); | ||
const client = await initializeUnleashClient(extensionName, serverArgs, [appStudioMultiStrategy]).catch((err) => { | ||
handleUnauthorisedError(extensionName); | ||
throw err; | ||
}); | ||
registerStrategies(appStudioMultiStrategy); | ||
@@ -36,2 +74,4 @@ | ||
handleUnauthorisedCalls(extensionName, initializeAttemptMap); | ||
// The client does NOT exist in the map -> create a new client | ||
@@ -38,0 +78,0 @@ return createNewUnleashClient(extensionName, unleashClientMap); |
@@ -38,2 +38,3 @@ import { initialize, Unleash, Strategy } from "unleash-client"; | ||
strategies: customStrategies, | ||
disableMetrics: true, | ||
}; | ||
@@ -40,0 +41,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
75343
1000
2
83