feat: bru cli - specify env + completed vars runtime

This commit is contained in:
Anoop M D 2023-02-07 21:01:35 +05:30
parent 78ca6c5e96
commit 3f74178c81
7 changed files with 162 additions and 89 deletions

View File

@ -1,27 +1,34 @@
const fs = require('fs');
const chalk = require('chalk');
const {
exists,
isFile,
isDirectory
} = require('../utils/filesystem');
const {
runSingleRequest
} = require('../runner/run-single-request');
const path = require('path');
const { exists, isFile } = require('../utils/filesystem');
const { runSingleRequest } = require('../runner/run-single-request');
const { bruToEnvJson, getEnvVars } = require('../utils/bru');
const command = 'run <filename>';
const desc = 'Run a request';
const builder = async (yargs) => {
yargs.example('$0 run request.bru', 'Run a request');
yargs
.option('env', {
describe: 'Environment variables',
type: 'string',
})
.example('$0 run request.bru', 'Run a request')
.example('$0 run request.bru --env local', 'Run a request with the environment set to local');
};
const handler = async function (argv) {
try {
const { filename } = argv;
const {
filename,
env
} = argv;
const pathExists = await exists(filename);
if(!pathExists) {
console.error(chalk.red(`File or directory ${filename} does not exist`));
return;
}
// todo
@ -30,14 +37,29 @@ const handler = async function (argv) {
const collectionPath = process.cwd();
const collectionVariables = {};
let envVars = {};
if(env) {
const envFile = path.join(collectionPath, 'environments', `${env}.bru`);
const envPathExists = await exists(envFile);
if(!envPathExists) {
console.error(chalk.red(`Environment file not found: `) + chalk.dim(`environments/${env}.bru`));
return;
}
const envBruContent = fs.readFileSync(envFile, 'utf8');
const envJson = bruToEnvJson(envBruContent);
envVars = getEnvVars(envJson);
}
const _isFile = await isFile(filename);
if(_isFile) {
console.log(chalk.yellow('Running Request \n'));
await runSingleRequest(filename, collectionPath, collectionVariables);
await runSingleRequest(filename, collectionPath, collectionVariables, envVars);
console.log(chalk.green('\nDone!'));
}
} catch (err) {
console.error(err);
// console.error(err.message);
}
};

View File

@ -1,41 +1,15 @@
const Mustache = require('mustache');
const fs = require('fs');
const chalk = require('chalk');
const { forOwn, each, extend, get } = require('lodash');
const FormData = require('form-data');
const path = require('path');
const axios = require('axios');
const prepareRequest = require('./prepare-request');
const interpolateVars = require('./interpolate-vars');
const { ScriptRuntime, TestRuntime, VarsRuntime } = require('@usebruno/js');
const {
bruToJson
} = require('./bru');
const {
stripExtension
} = require('../utils/filesystem');
const chalk = require('chalk');
const { bruToJson } = require('../utils/bru');
const { stripExtension } = require('../utils/filesystem');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {
return value;
};
const getEnvVars = (environment = {}) => {
const variables = environment.variables;
if (!variables || !variables.length) {
return {};
}
const envVars = {};
each(variables, (variable) => {
if(variable.enabled) {
envVars[variable.name] = Mustache.escape(variable.value);
}
});
return envVars;
};
const runSingleRequest = async function (filename, collectionPath, collectionVariables) {
const runSingleRequest = async function (filename, collectionPath, collectionVariables, envVariables) {
try {
const bruContent = fs.readFileSync(filename, 'utf8');
@ -53,30 +27,46 @@ const runSingleRequest = async function (filename, collectionPath, collectionVar
request.data = form;
}
const envVars = getEnvVars({});
// run pre-request vars
const preRequestVars = get(bruJson, 'request.vars.req');
if(preRequestVars && preRequestVars.length) {
const varsRuntime = new VarsRuntime();
varsRuntime.runPreRequestVars(preRequestVars, request, envVariables, collectionVariables, collectionPath);
}
// run pre request script
const requestScriptFile = get(bruJson, 'request.script.req');
if(requestScriptFile && requestScriptFile.length) {
const scriptRuntime = new ScriptRuntime();
const result = scriptRuntime.runRequestScript(requestScriptFile, request, envVars, collectionVariables, collectionPath);
scriptRuntime.runRequestScript(requestScriptFile, request, envVariables, collectionVariables, collectionPath);
}
// interpolate variables inside request
interpolateVars(request, envVariables, collectionVariables);
// run request
const response = await axios(request);
const varsRuntime = new VarsRuntime();
varsRuntime.runResponseVars(bruJson.request.vars.res, request, response, envVars, collectionVariables);
// run post-response vars
const postResponseVars = get(bruJson, 'request.vars.res');
if(postResponseVars && postResponseVars.length) {
const varsRuntime = new VarsRuntime();
varsRuntime.runPostResponseVars(postResponseVars, request, response, envVariables, collectionVariables, collectionPath);
}
// run post response script
const responseScriptFile = get(bruJson, 'request.script.res');
if(responseScriptFile && responseScriptFile.length) {
const scriptRuntime = new ScriptRuntime();
const result = scriptRuntime.runResponseScript(responseScriptFile, response, envVars, collectionVariables, collectionPath);
scriptRuntime.runResponseScript(responseScriptFile, response, envVariables, collectionVariables, collectionPath);
}
// run tests
let testResults = [];
const testFile = get(bruJson, 'request.tests');
if(testFile && testFile.length) {
const testRuntime = new TestRuntime();
const result = testRuntime.runTests(testFile, request, response, envVars, collectionVariables, collectionPath);
const result = testRuntime.runTests(testFile, request, response, envVariables, collectionVariables, collectionPath);
testResults = get(result, 'results', []);
}
@ -91,8 +81,7 @@ const runSingleRequest = async function (filename, collectionPath, collectionVar
});
}
} catch (err) {
console.log(err.response);
Promise.reject(err);
console.log(chalk.red(stripExtension(filename)) + chalk.dim(` (${err.message})`));
}
};

View File

@ -1,7 +1,11 @@
const _ = require('lodash');
const {
bruToJsonV2
} = require('@usebruno/lang');
const Mustache = require('mustache');
const { bruToEnvJsonV2, bruToJsonV2 } = require('@usebruno/lang');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {
return value;
};
/**
* The transformer function for converting a BRU file to JSON.
@ -52,6 +56,32 @@ const bruToJson = (bru) => {
}
};
module.exports = {
bruToJson
const bruToEnvJson = (bru) => {
try {
return bruToEnvJsonV2(bru);
} catch (err) {
return Promise.reject(err);
}
};
const getEnvVars = (environment = {}) => {
const variables = environment.variables;
if (!variables || !variables.length) {
return {};
}
const envVars = {};
_.each(variables, (variable) => {
if(variable.enabled) {
envVars[variable.name] = Mustache.escape(variable.value);
}
});
return envVars;
};
module.exports = {
bruToJson,
bruToEnvJson,
getEnvVars
};

View File

@ -9,10 +9,7 @@ const prepareGqlIntrospectionRequest = require('./prepare-gql-introspection-requ
const { cancelTokens, saveCancelToken, deleteCancelToken } = require('../../utils/cancel-token');
const { uuid } = require('../../utils/common');
const interpolateVars = require('./interpolate-vars');
const {
sortFolder,
getAllRequestsInFolderRecursively
} = require('./helper');
const { sortFolder, getAllRequestsInFolderRecursively } = require('./helper');
// override the default escape function to prevent escaping
Mustache.escape = function (value) {

View File

@ -1,12 +1,12 @@
class Bru {
constructor(environment, collectionVariables) {
this._environment = environment;
constructor(envVariables, collectionVariables) {
this._envVariables = envVariables;
this._collectionVariables = collectionVariables;
}
getEnvVar(key) {
return this._environment[key];
return this._envVariables[key];
}
setEnvVar(key, value) {
@ -15,11 +15,11 @@ class Bru {
}
// gracefully ignore if key is not present in environment
if(!this._environment.hasOwnProperty(key)) {
if(!this._envVariables.hasOwnProperty(key)) {
return;
}
this._environment[key] = value;
this._envVariables[key] = value;
}
setVar(key, value) {

View File

@ -0,0 +1,17 @@
const jsonQuery = require('json-query');
const evaluateJsExpression = (expression, context) => {
const fn = new Function(...Object.keys(context), `return ${expression}`);
return fn(...Object.values(context));
};
const createResponseParser = (res = {}) => (expr) => {
const output = jsonQuery(expr, { data: res.data });
return output ? output.value : null;
};
module.exports = {
evaluateJsExpression,
createResponseParser
};

View File

@ -1,43 +1,61 @@
const _ = require('lodash');
const Bru = require('./bru');
const BrunoRequest = require('./bruno-request');
const BrunoResponse = require('./bruno-response');
const _ = require('lodash');
const jsonQuery = require('json-query');
const { evaluateJsExpression, createResponseParser } = require('./utils');
class VarsRuntime {
constructor() {
}
runResponseVars(vars, request, response, environment, collectionVariables, collectionPath) {
const bru = new Bru(environment, collectionVariables);
const req = new BrunoRequest(request);
const res = new BrunoResponse(response);
res.q = function(expr) {
const output = jsonQuery(expr, {data: res.body});
return output.value;
runPreRequestVars(vars, request, envVariables, collectionVariables, collectionPath) {
const enabledVars = _.filter(vars, (v) => v.enabled);
if(!enabledVars.length) {
return;
}
const result = {
const bru = new Bru(envVariables, collectionVariables);
const req = new BrunoRequest(request);
const bruContext = {
bru,
req
};
const context = {
bru,
req,
res
...envVariables,
...collectionVariables,
...bruContext
}
console.log(JSON.stringify(vars, null, 2));
_.each(vars, (v) => {
result[v.name] = eval(v.value, context);
_.each(enabledVars, (v) => {
const value = evaluateJsExpression(v.value, context);
bru.setVar(v.name, value);
});
}
console.log(result);
runPostResponseVars(vars, request, response, envVariables, collectionVariables, collectionPath) {
const enabledVars = _.filter(vars, (v) => v.enabled);
if(!enabledVars.length) {
return;
}
const bru = new Bru(envVariables, collectionVariables);
const req = new BrunoRequest(request);
const res = createResponseParser(response);
const bruContext = {
bru,
req,
res
};
const context = {
...envVariables,
...collectionVariables,
...bruContext
}
_.each(enabledVars, (v) => {
const value = evaluateJsExpression(v.value, context);
bru.setVar(v.name, value);
});
}
}