diff --git a/.env-cmdrc-template b/.env-cmdrc-template index b82517d..aef5d62 100644 --- a/.env-cmdrc-template +++ b/.env-cmdrc-template @@ -18,6 +18,8 @@ "MAX_REQUEST_PER_MINUTE": 0, "SWITCHER_API_LOGGER": false, + "SWITCHER_API_LOGGER_LEVEL": "debug", + "SWITCHER_API_ENABLE": false, "SWITCHER_API_THROTTLE": 5000, "SWITCHER_API_URL": "http://localhost:3000", diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index ce0cb1e..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "env": { - "node": true, - "commonjs": false, - "es6": true, - "jest": true - }, - "extends": "eslint:recommended", - "rules": { - "quotes": [ - "error", - "single" - ], - "semi": [ - "error", - "always" - ] - }, - "parserOptions": { - "ecmaVersion": 2022, - "sourceType": "module", - "ecmaFeatures": { - "experimentalObjectRestSpread": true - } - } -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 9cf95c1..6bca640 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,6 +31,8 @@ services: - MAX_REQUEST_PER_MINUTE=${MAX_REQUEST_PER_MINUTE} - SWITCHER_API_LOGGER=${SWITCHER_API_LOGGER} + - SWITCHER_API_LOGGER_LEVEL=${SWITCHER_API_LOGGER_LEVEL} + - SWITCHER_API_ENABLE=${SWITCHER_API_ENABLE} - SWITCHER_API_URL=${SWITCHER_API_URL} - SWITCHER_API_KEY=${SWITCHER_API_KEY} diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..29ac66d --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,24 @@ +import js from '@eslint/js'; +import globals from 'globals'; + +export default [ + { + ...js.configs.recommended, + files: ['src/**/*.js'] + }, + { + files: ['src/**/*.js'], + rules: { + quotes: ['error', 'single'], + semi: ['error', 'always'], + curly: ['error', 'multi-line'], + }, + languageOptions: { + ecmaVersion: 2022, + sourceType: 'module', + globals: { + ...globals.node + } + } + } +]; \ No newline at end of file diff --git a/package.json b/package.json index 3574545..46f5cfc 100644 --- a/package.json +++ b/package.json @@ -49,9 +49,9 @@ "helmet": "^7.1.0", "jsonwebtoken": "^9.0.2", "moment": "^2.30.1", - "mongodb": "^6.6.1", - "mongoose": "^8.3.4", - "pino": "^9.0.0", + "mongodb": "^6.6.2", + "mongoose": "^8.4.0", + "pino": "^9.1.0", "pino-pretty": "^11.0.0", "swagger-ui-express": "^5.0.0", "switcher-client": "^4.1.0", @@ -59,12 +59,12 @@ }, "devDependencies": { "env-cmd": "^10.1.0", - "eslint": "^8.57.0", + "eslint": "^9.3.0", "jest": "^29.7.0", "jest-sonar-reporter": "^2.0.0", "node-notifier": "^10.0.1", "nodemon": "^3.1.0", - "sinon": "^17.0.2", + "sinon": "^18.0.0", "supertest": "^7.0.0" }, "repository": { diff --git a/src/client/relay/index.js b/src/client/relay/index.js index 3346093..27aa193 100644 --- a/src/client/relay/index.js +++ b/src/client/relay/index.js @@ -2,6 +2,7 @@ import axios from 'axios'; import https from 'https'; import { StrategiesToRelayDataType, RelayMethods } from '../../models/config.js'; import { checkHttpsAgent } from '../../external/switcher-api-facade.js'; +import Logger from '../../helpers/logger.js'; const agent = async (url) => { const response = await checkHttpsAgent(url); @@ -44,6 +45,7 @@ async function post(url, data, headers) { try { return await axios.post(url, data, { httpsAgent: await agent(url), headers }); } catch (error) { + Logger.debug('post', error); throw new Error(`Failed to reach ${url} via POST`); } } @@ -52,6 +54,7 @@ async function get(url, data, headers) { try { return await axios.get(`${url}${data}`, { httpsAgent: await agent(url), headers }); } catch (error) { + Logger.debug('get', error); throw new Error(`Failed to reach ${url} via GET`); } } diff --git a/src/client/resolvers.js b/src/client/resolvers.js index bf843ea..886d7c8 100644 --- a/src/client/resolvers.js +++ b/src/client/resolvers.js @@ -171,8 +171,9 @@ function checkFlags(config, group, domain, environment) { async function checkStrategy(entry, strategies, environment) { if (strategies) { for (const strategy of strategies) { - if (!strategy.activated[environment]) + if (!strategy.activated[environment]) { continue; + } await checkStrategyInput(entry, strategy); } diff --git a/src/external/switcher-api-facade.js b/src/external/switcher-api-facade.js index 2f74f18..a4b1628 100644 --- a/src/external/switcher-api-facade.js +++ b/src/external/switcher-api-facade.js @@ -44,8 +44,9 @@ export async function getRateLimit(key, component) { } export async function checkHttpsAgent(value) { - if (process.env.SWITCHER_API_ENABLE != 'true') + if (process.env.SWITCHER_API_ENABLE != 'true') { return; + } return getFeatureFlag(SwitcherKeys.HTTPS_AGENT) .checkRegex(value) diff --git a/src/helpers/index.js b/src/helpers/index.js index 65f1cde..70a1f68 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -1,15 +1,19 @@ +import Logger from './logger.js'; + export function payloadReader(payload) { let payloadRead = payload + '' === payload || payload || 0; - if (Array.isArray(payloadRead)) + if (Array.isArray(payloadRead)) { return payloadRead.flatMap(p => payloadReader(p)); + } return Object.keys(payloadRead) .flatMap(field => [field, ...payloadReader(payload[field]) .map(nestedField => `${field}.${nestedField}`)]) .filter(field => isNaN(Number(field))) .reduce((acc, curr) => { - if (!acc.includes(curr)) + if (!acc.includes(curr)) { acc.push(curr); + } return acc; }, []); } @@ -18,6 +22,7 @@ export function parseJSON(str) { try { return JSON.parse(str); } catch (e) { + Logger.debug('parseJSON', e); return undefined; } } \ No newline at end of file diff --git a/src/helpers/logger.js b/src/helpers/logger.js index 236d0b2..2072e10 100644 --- a/src/helpers/logger.js +++ b/src/helpers/logger.js @@ -1,6 +1,7 @@ import pino from 'pino'; const logger = pino({ + level: process.env.SWITCHER_API_LOGGER_LEVEL || 'info', transport: { target: 'pino-pretty' } @@ -12,17 +13,26 @@ export default class Logger { } static info(message, obj) { - if (process.env.SWITCHER_API_LOGGER == 'true') + if (process.env.SWITCHER_API_LOGGER == 'true') { logger.info(obj, message); + } } static error(message, err) { - if (process.env.SWITCHER_API_LOGGER == 'true') + if (process.env.SWITCHER_API_LOGGER == 'true') { logger.error(err, message); + } + } + + static debug(message, obj) { + if (process.env.SWITCHER_API_LOGGER == 'true') { + logger.debug(obj, message); + } } static httpError(name, code, message, err) { - if (process.env.SWITCHER_API_LOGGER == 'true') + if (process.env.SWITCHER_API_LOGGER == 'true') { logger.error(err, `${name} [${code}]: ${message}`); + } } } \ No newline at end of file diff --git a/src/helpers/timed-match/index.js b/src/helpers/timed-match/index.js index fa3a877..c903936 100644 --- a/src/helpers/timed-match/index.js +++ b/src/helpers/timed-match/index.js @@ -27,8 +27,9 @@ export default class TimedMatch { let result = false; let timer, resolveListener; - if (this._isBlackListed({ values, input })) + if (this._isBlackListed({ values, input })) { return false; + } const matchPromise = new Promise((resolve) => { resolveListener = resolve; @@ -88,8 +89,9 @@ export default class TimedMatch { this._worker.kill(); this._worker = this._createChildProcess(); - if (this._blacklisted.length == this._maxBlackListed) + if (this._blacklisted.length == this._maxBlackListed) { this._blacklisted.splice(0, 1); + } this._blacklisted.push({ res: values, diff --git a/src/middleware/limiter.js b/src/middleware/limiter.js index 73984cd..723ab35 100644 --- a/src/middleware/limiter.js +++ b/src/middleware/limiter.js @@ -6,8 +6,9 @@ const ERROR_MESSAGE = { }; const getMaxRate = (rate_limit) => { - if (rate_limit === 0) + if (rate_limit === 0) { return parseInt(DEFAULT_RATE_LIMIT); + } return rate_limit; }; diff --git a/src/models/config-strategy.js b/src/models/config-strategy.js index 3c38673..a5ea6ad 100644 --- a/src/models/config-strategy.js +++ b/src/models/config-strategy.js @@ -156,8 +156,9 @@ async function processREGEX(operation, input, values) { function processPAYLOAD(operation, input, values) { const inputJson = parseJSON(input); - if (!inputJson) + if (!inputJson) { return false; + } const keys = payloadReader(inputJson); switch(operation) { diff --git a/src/services/config.js b/src/services/config.js index 8e744a0..561c341 100644 --- a/src/services/config.js +++ b/src/services/config.js @@ -23,22 +23,26 @@ export async function getConfigs(where) { export function isRelayValid(relay) { const bypass = process.env.RELAY_BYPASS_HTTPS === 'true' || false; - if (bypass || !relay.endpoint) + if (bypass || !relay.endpoint) { return; + } const foundNotHttps = Object.values(relay.endpoint) .filter(endpoint => !endpoint.toLowerCase().startsWith('https')); - if (foundNotHttps.length) + if (foundNotHttps.length) { throw new BadRequestError('HTTPS required'); + } } export function isRelayVerified(relay, environment) { const bypass = process.env.RELAY_BYPASS_VERIFICATION === 'true' || false; - if (bypass) + if (bypass) { return; + } - if (!relay.verified[environment]) + if (!relay.verified[environment]) { throw new BadRequestError('Relay not verified'); + } } \ No newline at end of file