diff --git a/packages/bruno-lang/v2/src/bruToJson.js b/packages/bruno-lang/v2/src/bruToJson.js index 289e9b5b6..3248f4b54 100644 --- a/packages/bruno-lang/v2/src/bruToJson.js +++ b/packages/bruno-lang/v2/src/bruToJson.js @@ -138,7 +138,7 @@ const sem = grammar.createSemantics().addAttribute('ast', { return res; }, key(chars) { - return chars.sourceString; + return chars.sourceString ? chars.sourceString.trim() : ''; }, value(chars) { return chars.sourceString ? chars.sourceString.trim() : ''; diff --git a/packages/bruno-lang/v2/src/envToJson.js b/packages/bruno-lang/v2/src/envToJson.js new file mode 100644 index 000000000..ec638fe35 --- /dev/null +++ b/packages/bruno-lang/v2/src/envToJson.js @@ -0,0 +1,108 @@ +const ohm = require("ohm-js"); +const _ = require('lodash'); + +const grammar = ohm.grammar(`Bru { + BruEnvFile = (vars)* + + nl = "\\r"? "\\n" + st = " " | "\\t" + tagend = nl "}" + validkey = ~(st | ":") any + validvalue = ~nl any + + // Dictionary Blocks + dictionary = st* "{" pairlist? tagend + pairlist = nl* pair (~tagend nl pair)* (~tagend space)* + pair = st* key st* ":" st* value? st* + key = ~tagend validkey* + value = ~tagend validvalue* + + vars = "vars" dictionary +}`); + +const mapPairListToKeyValPairs = (pairList = []) => { + if(!pairList.length) { + return []; + } + + return _.map(pairList[0], pair => { + let name = _.keys(pair)[0]; + let value = pair[name]; + let enabled = true; + if (name && name.length && name.charAt(0) === "~") { + name = name.slice(1); + enabled = false; + } + + return { + name, + value, + enabled + }; + }); +}; + +const concatArrays = (objValue, srcValue) => { + if (_.isArray(objValue) && _.isArray(srcValue)) { + return objValue.concat(srcValue); + } +}; + +const sem = grammar.createSemantics().addAttribute('ast', { + BruEnvFile(tags) { + if(!tags || !tags.ast || !tags.ast.length) { + return {}; + } + + return _.reduce(tags.ast, (result, item) => { + return _.mergeWith(result, item, concatArrays); + }, {}); + }, + dictionary(_1, _2, pairlist, _3) { + return pairlist.ast; + }, + pairlist(_1, pair, _2, rest, _3) { + return [pair.ast, ...rest.ast]; + }, + pair(_1, key, _2, _3, _4, value, _5) { + let res = {}; + res[key.ast] = _.get(value, 'ast[0]', ''); + return res; + }, + key(chars) { + return chars.sourceString ? chars.sourceString.trim() : ''; + }, + value(chars) { + return chars.sourceString ? chars.sourceString.trim() : ''; + }, + nl(_1, _2) { + return ''; + }, + st(_) { + return ''; + }, + tagend(_1 ,_2) { + return ''; + }, + _iter(...elements) { + return elements.map(e => e.ast); + }, + vars(_1, dictionary) { + const vars = mapPairListToKeyValPairs(dictionary.ast); + return { + variables: vars + }; + } +}); + +const parser = (input) => { + const match = grammar.match(input); + + if(match.succeeded()) { + return sem(match).ast; + } else { + throw new Error(match.message); + } +} + +module.exports = parser; diff --git a/packages/bruno-lang/v2/src/jsonToEnv.js b/packages/bruno-lang/v2/src/jsonToEnv.js new file mode 100644 index 000000000..9ae3d6e87 --- /dev/null +++ b/packages/bruno-lang/v2/src/jsonToEnv.js @@ -0,0 +1,25 @@ +const _ = require('lodash'); + +const envToJson = (json) => { + const variables = _.get(json, 'variables', []); + const vars = variables.map((variable) => { + const { name, value, enabled } = variable; + const prefix = enabled ? '' : '~'; + return ` ${prefix}${name}: ${value}`; + }); + + if(!vars || !vars.length) { + return `vars { +} +`; + } + + const output = `vars { +${vars.join('\n')} +} +`; + + return output; +}; + +module.exports = envToJson; diff --git a/packages/bruno-lang/v2/tests/envToJson.spec.js b/packages/bruno-lang/v2/tests/envToJson.spec.js new file mode 100644 index 000000000..ee9439933 --- /dev/null +++ b/packages/bruno-lang/v2/tests/envToJson.spec.js @@ -0,0 +1,88 @@ +const parser = require("../src/envToJson"); + +describe("env parser", () => { + it("should parse empty vars", () => { + const input = ` +vars { +}`; + + const output = parser(input); + const expected = { + "variables": [] + }; + + expect(output).toEqual(expected); + }); + + it("should parse single var line", () => { + const input = ` +vars { + url: http://localhost:3000 +}`; + + const output = parser(input); + const expected = { + "variables": [{ + "name": "url", + "value": "http://localhost:3000", + "enabled" : true, + }] + }; + + expect(output).toEqual(expected); + }); + + it("should parse multiple var lines", () => { + const input = ` +vars { + url: http://localhost:3000 + port: 3000 + ~token: secret +}`; + + const output = parser(input); + const expected = { + "variables": [{ + "name": "url", + "value": "http://localhost:3000", + "enabled" : true + }, { + "name": "port", + "value": "3000", + "enabled" : true + }, { + "name": "token", + "value": "secret", + "enabled" : false + }] + }; + + expect(output).toEqual(expected); + }); + + it("should gracefully handle empty lines and spaces", () => { + const input = ` + +vars { + url: http://localhost:3000 + port: 3000 +} + +`; + + const output = parser(input); + const expected = { + "variables": [{ + "name": "url", + "value": "http://localhost:3000", + "enabled" : true, + }, { + "name": "port", + "value": "3000", + "enabled" : true, + }] + }; + + expect(output).toEqual(expected); + }); +}); diff --git a/packages/bruno-lang/v2/tests/jsonToEnv.spec.js b/packages/bruno-lang/v2/tests/jsonToEnv.spec.js new file mode 100644 index 000000000..4ff471f64 --- /dev/null +++ b/packages/bruno-lang/v2/tests/jsonToEnv.spec.js @@ -0,0 +1,55 @@ +const parser = require("../src/jsonToEnv"); + +describe("env parser", () => { + it("should parse empty vars", () => { + const input = { + "variables": [] + }; + + const output = parser(input); + const expected = `vars { +} +`; + + expect(output).toEqual(expected); + }); + + it("should parse single var line", () => { + const input = { + "variables": [{ + "name": "url", + "value": "http://localhost:3000", + "enabled" : true, + }] + }; + + const output = parser(input); + const expected = `vars { + url: http://localhost:3000 +} +`; + expect(output).toEqual(expected); + }); + + it("should parse multiple var lines", () => { + const input = { + "variables": [{ + "name": "url", + "value": "http://localhost:3000", + "enabled" : true + }, { + "name": "port", + "value": "3000", + "enabled" : false + }] + }; + + const expected = `vars { + url: http://localhost:3000 + ~port: 3000 +} +`; + const output = parser(input); + expect(output).toEqual(expected); + }); +});