Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions src/lib/resolver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { processOperation } from './snapshot.js';
import { getEntry } from '../lib/remote.js';
import * as util from '../lib/utils/index.js';

async function resolveCriteria(key, input, { domain }) {
async function resolveCriteria({ domain }, switcher) {
let result = true, reason = '';

try {
Expand All @@ -10,8 +11,8 @@ async function resolveCriteria(key, input, { domain }) {
}

const { group } = domain;
if (!(await checkGroup(group, key, input))) {
throw new Error(`Something went wrong: {"error":"Unable to load a key ${key}"}`);
if (!(await checkGroup(group, switcher))) {
throw new Error(`Something went wrong: {"error":"Unable to load a key ${switcher.key}"}`);
}

reason = 'Success';
Expand All @@ -32,18 +33,19 @@ async function resolveCriteria(key, input, { domain }) {

/**
* @param {*} groups from a specific Domain
* @param {*} key to be filtered
* @param {*} input strategy if exists
* @param {*} switcher Switcher to check
* @return true if Switcher found
*/
async function checkGroup(groups, key, input) {
async function checkGroup(groups, switcher) {
const key = util.get(switcher.key, '');

if (groups) {
for (const group of groups) {
const { config } = group;
const configFound = config.filter(c => c.key === key);

// Switcher Configs are always supplied as the snapshot is loaded from components linked to the Switcher.
if (await checkConfig(group, configFound[0], input)) {
if (await checkConfig(group, configFound[0], switcher)) {
return true;
}
}
Expand All @@ -54,10 +56,10 @@ async function checkGroup(groups, key, input) {
/**
* @param {*} group in which Switcher has been found
* @param {*} config Switcher found
* @param {*} input Strategy input if exists
* @param {*} switcher Switcher to check
* @return true if Switcher found
*/
async function checkConfig(group, config, input) {
async function checkConfig(group, config, switcher) {
if (!config) {
return false;
}
Expand All @@ -71,7 +73,7 @@ async function checkConfig(group, config, input) {
}

if (config.strategies) {
return await checkStrategy(config, input);
return await checkStrategy(config, util.get(switcher.input, []));
}

return true;
Expand Down Expand Up @@ -103,13 +105,13 @@ async function checkStrategyInput(entry, { strategy, operation, values }) {
}
}

export default async function checkCriteriaLocal(key, input, snapshot) {
export default async function checkCriteriaLocal(snapshot, switcher) {
if (!snapshot) {
throw new Error('Snapshot not loaded. Try to use \'Client.loadSnapshot()\'');
}

const { data } = snapshot;
return resolveCriteria(key, input, data);
return resolveCriteria(data, switcher);
}

class CriteriaFailed extends Error {
Expand Down
143 changes: 29 additions & 114 deletions src/switcher.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,24 @@
import Bypasser from './lib/bypasser/index.js';
import ExecutionLogger from './lib/utils/executionLogger.js';
import checkCriteriaLocal from './lib/resolver.js';
import { StrategiesType } from './lib/snapshot.js';
import * as remote from './lib/remote.js';
import * as util from './lib/utils/index.js';
import { Auth } from './lib/remoteAuth.js';
import { GlobalAuth } from './lib/globals/globalAuth.js';
import { GlobalOptions } from './lib/globals/globalOptions.js';
import { GlobalSnapshot } from './lib/globals/globalSnapshot.js';
import { SwitcherRequest } from './switcherRequest.js';

export class Switcher {
#delay = 0;
#nextRun = 0;
#input;
#key = '';
#defaultResult;
#forceRemote = false;
#showDetail = false;

export class Switcher extends SwitcherRequest {
constructor(key) {
super();
this.#validateArgs(key);
}

async prepare(key) {
this.#validateArgs(key);

if (!GlobalOptions.local || this.#forceRemote) {
if (!GlobalOptions.local || this._forceRemote) {
await Auth.auth();
}
}
Expand All @@ -35,7 +28,7 @@ export class Switcher {

Auth.isValid();

if (!this.#key) {
if (!this._key) {
errors.push('Missing key field');
}

Expand All @@ -54,15 +47,15 @@ export class Switcher {
this.#validateArgs(key);

// verify if query from Bypasser
const bypassKey = Bypasser.searchBypassed(this.#key);
const bypassKey = Bypasser.searchBypassed(this._key);
if (bypassKey) {
const response = bypassKey.getResponse(util.get(this.#input, []));
return this.#showDetail ? response : response.result;
const response = bypassKey.getResponse(util.get(this._input, []));
return this._showDetail ? response : response.result;
}

try {
// verify if query from local snapshot
if (GlobalOptions.local && !this.#forceRemote) {
if (GlobalOptions.local && !this._forceRemote) {
return await this._executeLocalCriteria();
}

Expand All @@ -87,116 +80,50 @@ export class Switcher {
return result;
}

throttle(delay) {
this.#delay = delay;

if (delay > 0) {
GlobalOptions.updateOptions({ logger: true });
}

return this;
}

remote(forceRemote = true) {
if (!GlobalOptions.local) {
throw new Error('Local mode is not enabled');
}

this.#forceRemote = forceRemote;
return this;
}

detail(showDetail = true) {
this.#showDetail = showDetail;
return this;
}

defaultResult(defaultResult) {
this.#defaultResult = defaultResult;
return this;
}

check(startegyType, input) {
if (!this.#input) {
this.#input = [];
}

this.#input.push([startegyType, input]);
return this;
}

checkValue(input) {
return this.check(StrategiesType.VALUE, input);
}

checkNumeric(input) {
return this.check(StrategiesType.NUMERIC, input);
}

checkNetwork(input) {
return this.check(StrategiesType.NETWORK, input);
}

checkDate(input) {
return this.check(StrategiesType.DATE, input);
}

checkTime(input) {
return this.check(StrategiesType.TIME, input);
}

checkRegex(input) {
return this.check(StrategiesType.REGEX, input);
}

checkPayload(input) {
return this.check(StrategiesType.PAYLOAD, input);
}

async _executeRemoteCriteria() {
let responseCriteria;

if (this.#useSync()) {
try {
responseCriteria = await remote.checkCriteria(
this.#key,
this.#input,
this.#showDetail
this._key,
this._input,
this._showDetail
);
} catch (err) {
responseCriteria = this.#getDefaultResultOrThrow(err);
}

if (GlobalOptions.logger && this.#key) {
ExecutionLogger.add(responseCriteria, this.#key, this.#input);
if (GlobalOptions.logger && this._key) {
ExecutionLogger.add(responseCriteria, this._key, this._input);
}
} else {
responseCriteria = this._executeAsyncRemoteCriteria();
}

return this.#showDetail ? responseCriteria : responseCriteria.result;
return this._showDetail ? responseCriteria : responseCriteria.result;
}

_executeAsyncRemoteCriteria() {
if (this.#nextRun < Date.now()) {
this.#nextRun = Date.now() + this.#delay;
if (this._nextRun < Date.now()) {
this._nextRun = Date.now() + this._delay;

if (Auth.isTokenExpired()) {
this.prepare(this.#key)
this.prepare(this._key)
.then(() => this.#executeAsyncCheckCriteria())
.catch(err => this.#notifyError(err));
} else {
this.#executeAsyncCheckCriteria();
}
}

const executionLog = ExecutionLogger.getExecution(this.#key, this.#input);
const executionLog = ExecutionLogger.getExecution(this._key, this._input);
return executionLog.response;
}

#executeAsyncCheckCriteria() {
remote.checkCriteria(this.#key, this.#input, this.#showDetail)
.then(response => ExecutionLogger.add(response, this.#key, this.#input))
remote.checkCriteria(this._key, this._input, this._showDetail)
.then(response => ExecutionLogger.add(response, this._key, this._input))
.catch(err => this.#notifyError(err));
}

Expand All @@ -211,27 +138,23 @@ export class Switcher {

Auth.checkHealth();
if (Auth.isTokenExpired()) {
await this.prepare(this.#key);
await this.prepare(this._key);
}
}

async _executeLocalCriteria() {
let response;
try {
response = await checkCriteriaLocal(
util.get(this.#key, ''),
util.get(this.#input, []),
GlobalSnapshot.snapshot
);
response = await checkCriteriaLocal(GlobalSnapshot.snapshot, this);
} catch (err) {
response = this.#getDefaultResultOrThrow(err);
}

if (GlobalOptions.logger) {
ExecutionLogger.add(response, this.#key, this.#input);
ExecutionLogger.add(response, this._key, this._input);
}

if (this.#showDetail) {
if (this._showDetail) {
return response;
}

Expand All @@ -240,34 +163,26 @@ export class Switcher {

#validateArgs(key) {
if (key) {
this.#key = key;
this._key = key;
}
}

#useSync() {
return this.#delay == 0 || !ExecutionLogger.getExecution(this.#key, this.#input);
return this._delay == 0 || !ExecutionLogger.getExecution(this._key, this._input);
}

#getDefaultResultOrThrow(err) {
if (this.#defaultResult === undefined) {
if (this._defaultResult === undefined) {
throw err;
}

const response = {
result: this.#defaultResult,
result: this._defaultResult,
reason: 'Default result'
};

this.#notifyError(err);
return response;
}

get key() {
return this.#key;
}

get input() {
return this.#input;
}

}
Loading