From 1c4c5cc0c0735c00a95149b0774ade9397a4605b Mon Sep 17 00:00:00 2001 From: Anoop M D Date: Fri, 22 Sep 2023 00:27:27 +0530 Subject: [PATCH] feat(#122): Support parsing of dotenv files --- packages/bruno-lang/v2/src/dotenvToJson.js | 76 +++++++++++++++++++ .../bruno-lang/v2/tests/dotenvToJson.spec.js | 44 +++++++++++ 2 files changed, 120 insertions(+) create mode 100644 packages/bruno-lang/v2/src/dotenvToJson.js create mode 100644 packages/bruno-lang/v2/tests/dotenvToJson.spec.js diff --git a/packages/bruno-lang/v2/src/dotenvToJson.js b/packages/bruno-lang/v2/src/dotenvToJson.js new file mode 100644 index 000000000..403230326 --- /dev/null +++ b/packages/bruno-lang/v2/src/dotenvToJson.js @@ -0,0 +1,76 @@ +const ohm = require("ohm-js"); +const _ = require('lodash'); + +const grammar = ohm.grammar(`Env { + EnvFile = (entry)* + entry = st* key st* "=" st* value st* nl* + key = keychar* + value = valuechar* + keychar = ~(nl | st | nl | "=") any + valuechar = ~nl any + nl = "\\r"? "\\n" + st = " " | "\\t" +}`); + +const concatArrays = (objValue, srcValue) => { + if (_.isArray(objValue) && _.isArray(srcValue)) { + return objValue.concat(srcValue); + } +}; + +const sem = grammar.createSemantics().addAttribute('ast', { + EnvFile(entries) { + return _.reduce(entries.ast, (result, item) => { + return _.mergeWith(result, item, concatArrays); + }, {}); + }, + entry(_1, key, _2, _3, _4, value, _5, _6) { + return { [key.ast.trim()]: value.ast.trim() }; + }, + key(chars) { + return chars.sourceString; + }, + value(chars) { + return chars.sourceString; + }, + nl(_1, _2) { + return ''; + }, + st(_) { + return ''; + }, + _iter(...elements) { + return elements.map(e => e.ast); + } +}); + +const parser = (input) => { + const match = grammar.match(input); + + if (match.succeeded()) { + const ast = sem(match).ast; + return postProcessEntries(ast); + } else { + throw new Error(match.message); + } +} + +function postProcessEntries(ast) { + const processed = {}; + + for (const key in ast) { + const value = ast[key]; + + if (!isNaN(value)) { + processed[key] = parseFloat(value); // Convert to number if it's a valid number + } else if (value.toLowerCase() === 'true' || value.toLowerCase() === 'false') { + processed[key] = value.toLowerCase() === 'true'; // Convert to boolean if it's 'true' or 'false' + } else { + processed[key] = value; // Otherwise, keep it as a string + } + } + + return processed; +} + +module.exports = parser; diff --git a/packages/bruno-lang/v2/tests/dotenvToJson.spec.js b/packages/bruno-lang/v2/tests/dotenvToJson.spec.js new file mode 100644 index 000000000..47b063639 --- /dev/null +++ b/packages/bruno-lang/v2/tests/dotenvToJson.spec.js @@ -0,0 +1,44 @@ +const parser = require('../src/dotenvToJson'); + +describe('DotEnv File Parser', () => { + test('it should parse a simple key-value pair', () => { + const input = `FOO=bar`; + const expected = { FOO: 'bar' }; + const output = parser(input); + expect(output).toEqual(expected); + }); + + test('it should parse a simple key-value pair with empty lines', () => { + const input = ` +FOO=bar + +`; + const expected = { FOO: 'bar' }; + const output = parser(input); + expect(output).toEqual(expected); + }); + + test('it should parse multiple key-value pairs', () => { + const input = ` +FOO=bar +BAZ=2 +BEEP=false +`; + const expected = { + FOO: 'bar', + BAZ: 2, + BEEP: false, + }; + const output = parser(input); + expect(output).toEqual(expected); + }); + + test('it should handle leading and trailing whitespace', () => { + const input = ` + SPACE = value +`; + const expected = { SPACE: 'value' }; + const output = parser(input); + expect(output).toEqual(expected); + }); +});