From eb6b75ff9806f2437feee87a2ff6b92208fd2ec9 Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Mon, 25 Sep 2023 02:10:12 +0530 Subject: [PATCH] feat(#199): bru cli updates to load .env vars --- packages/bruno-cli/changelog.md | 9 +++- packages/bruno-cli/package.json | 7 +-- packages/bruno-cli/src/commands/run.js | 35 ++++++++++++++- .../bruno-cli/src/runner/interpolate-vars.js | 43 +++++++++++++++---- .../src/runner/run-single-request.js | 11 ++++- packages/bruno-js/package.json | 2 +- packages/bruno-lang/package.json | 2 +- packages/bruno-schema/package.json | 2 +- 8 files changed, 91 insertions(+), 20 deletions(-) diff --git a/packages/bruno-cli/changelog.md b/packages/bruno-cli/changelog.md index 49b0126d2..10045c025 100644 --- a/packages/bruno-cli/changelog.md +++ b/packages/bruno-cli/changelog.md @@ -1,9 +1,14 @@ # Changelog +## 0.8.0 + +- `--env-var` flag to set environment variables +- loading environment variables from `.env` file + ## 0.7.1 -* `--cacert` flag to support custom CA certificates +- `--cacert` flag to support custom CA certificates ## 0.7.0 -* `--insecure` flag to disable SSL verification \ No newline at end of file +- `--insecure` flag to disable SSL verification diff --git a/packages/bruno-cli/package.json b/packages/bruno-cli/package.json index 8a517db55..c8acd5232 100644 --- a/packages/bruno-cli/package.json +++ b/packages/bruno-cli/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/cli", - "version": "0.7.1", + "version": "0.8.0", "main": "src/index.js", "bin": { "bru": "./bin/bru.js" @@ -20,13 +20,14 @@ "package.json" ], "dependencies": { - "@usebruno/js": "0.4.0", - "@usebruno/lang": "0.3.0", + "@usebruno/js": "0.5.0", + "@usebruno/lang": "0.4.0", "axios": "^1.3.2", "chai": "^4.3.7", "chalk": "^3.0.0", "form-data": "^4.0.0", "fs-extra": "^10.1.0", + "handlebars": "^4.7.8", "inquirer": "^9.1.4", "lodash": "^4.17.21", "mustache": "^4.2.0", diff --git a/packages/bruno-cli/src/commands/run.js b/packages/bruno-cli/src/commands/run.js index 4b6aa3afa..62d53246c 100644 --- a/packages/bruno-cli/src/commands/run.js +++ b/packages/bruno-cli/src/commands/run.js @@ -1,11 +1,13 @@ const fs = require('fs'); const chalk = require('chalk'); const path = require('path'); +const { forOwn } = require('lodash'); const { exists, isFile, isDirectory } = require('../utils/filesystem'); const { runSingleRequest } = require('../runner/run-single-request'); const { bruToEnvJson, getEnvVars } = require('../utils/bru'); const { rpad } = require('../utils/common'); const { bruToJson, getOptions } = require('../utils/bru'); +const { dotenvToJson } = require('@usebruno/lang'); const command = 'run [filename]'; const desc = 'Run a request'; @@ -225,12 +227,34 @@ const handler = async function (argv) { } } + // load .env file at root of collection if it exists + const dotEnvPath = path.join(collectionPath, '.env'); + const dotEnvExists = await exists(dotEnvPath); + const processEnvVars = { + ...process.env + }; + if (dotEnvExists) { + const content = fs.readFileSync(dotEnvPath, 'utf8'); + const jsonData = dotenvToJson(content); + + forOwn(jsonData, (value, key) => { + processEnvVars[key] = value; + }); + } + const _isFile = await isFile(filename); if (_isFile) { console.log(chalk.yellow('Running Request \n')); const bruContent = fs.readFileSync(filename, 'utf8'); const bruJson = bruToJson(bruContent); - const result = await runSingleRequest(filename, bruJson, collectionPath, collectionVariables, envVars); + const result = await runSingleRequest( + filename, + bruJson, + collectionPath, + collectionVariables, + envVars, + processEnvVars + ); if (result) { const { assertionResults, testResults } = result; @@ -281,7 +305,14 @@ const handler = async function (argv) { for (const iter of bruJsons) { const { bruFilepath, bruJson } = iter; - const result = await runSingleRequest(bruFilepath, bruJson, collectionPath, collectionVariables, envVars); + const result = await runSingleRequest( + bruFilepath, + bruJson, + collectionPath, + collectionVariables, + envVars, + processEnvVars + ); if (result) { const { assertionResults: _assertionResults, testResults: _testResults } = result; diff --git a/packages/bruno-cli/src/runner/interpolate-vars.js b/packages/bruno-cli/src/runner/interpolate-vars.js index abd76ad47..bfb0601da 100644 --- a/packages/bruno-cli/src/runner/interpolate-vars.js +++ b/packages/bruno-cli/src/runner/interpolate-vars.js @@ -1,24 +1,51 @@ -const Mustache = require('mustache'); -const { each, forOwn } = require('lodash'); +const Handlebars = require('handlebars'); +const { each, forOwn, cloneDeep } = require('lodash'); -// override the default escape function to prevent escaping -Mustache.escape = function (value) { - return value; +const interpolateEnvVars = (str, processEnvVars) => { + if (!str || !str.length || typeof str !== 'string') { + return str; + } + + const template = Handlebars.compile(str, { noEscape: true }); + + return template({ + process: { + env: { + ...processEnvVars + } + } + }); }; -const interpolateVars = (request, envVars = {}, collectionVariables = {}) => { +const interpolateVars = (request, envVars = {}, collectionVariables = {}, processEnvVars = {}) => { + // we clone envVars because we don't want to modify the original object + envVars = cloneDeep(envVars); + + // envVars can inturn have values as {{process.env.VAR_NAME}} + // so we need to interpolate envVars first with processEnvVars + forOwn(envVars, (value, key) => { + envVars[key] = interpolateEnvVars(value, processEnvVars); + }); + const interpolate = (str) => { if (!str || !str.length || typeof str !== 'string') { return str; } + const template = Handlebars.compile(str, { noEscape: true }); + // collectionVariables take precedence over envVars const combinedVars = { ...envVars, - ...collectionVariables + ...collectionVariables, + process: { + env: { + ...processEnvVars + } + } }; - return Mustache.render(str, combinedVars); + return template(combinedVars); }; request.url = interpolate(request.url); diff --git a/packages/bruno-cli/src/runner/run-single-request.js b/packages/bruno-cli/src/runner/run-single-request.js index d108341bf..50bb7d546 100644 --- a/packages/bruno-cli/src/runner/run-single-request.js +++ b/packages/bruno-cli/src/runner/run-single-request.js @@ -11,7 +11,14 @@ const { ScriptRuntime, TestRuntime, VarsRuntime, AssertRuntime } = require('@use const { stripExtension } = require('../utils/filesystem'); const { getOptions } = require('../utils/bru'); -const runSingleRequest = async function (filename, bruJson, collectionPath, collectionVariables, envVariables) { +const runSingleRequest = async function ( + filename, + bruJson, + collectionPath, + collectionVariables, + envVariables, + processEnvVars +) { let request; try { @@ -49,7 +56,7 @@ const runSingleRequest = async function (filename, bruJson, collectionPath, coll } // interpolate variables inside request - interpolateVars(request, envVariables, collectionVariables); + interpolateVars(request, envVariables, collectionVariables, processEnvVars); const options = getOptions(); const insecure = get(options, 'insecure', false); diff --git a/packages/bruno-js/package.json b/packages/bruno-js/package.json index 7bf8e3a21..ad28493a1 100644 --- a/packages/bruno-js/package.json +++ b/packages/bruno-js/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/js", - "version": "0.4.0", + "version": "0.5.0", "main": "src/index.js", "files": [ "src", diff --git a/packages/bruno-lang/package.json b/packages/bruno-lang/package.json index 9a8869f24..d820ccfb0 100644 --- a/packages/bruno-lang/package.json +++ b/packages/bruno-lang/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/lang", - "version": "0.3.0", + "version": "0.4.0", "main": "src/index.js", "files": [ "src", diff --git a/packages/bruno-schema/package.json b/packages/bruno-schema/package.json index 5b177aaa5..3c6704e3d 100644 --- a/packages/bruno-schema/package.json +++ b/packages/bruno-schema/package.json @@ -1,6 +1,6 @@ { "name": "@usebruno/schema", - "version": "0.3.1", + "version": "0.4.0", "main": "src/index.js", "files": [ "src",