diff --git a/packages/bruno-lang/src/index.js b/packages/bruno-lang/src/index.js index e5731e61..01a25785 100644 --- a/packages/bruno-lang/src/index.js +++ b/packages/bruno-lang/src/index.js @@ -4,6 +4,10 @@ const { anyChar } = require("arcsecond"); const _ = require('lodash'); +const { + safeParseJson, + indentString +} = require('./utils'); const inlineTag = require('./inline-tag'); const paramsTag = require('./params-tag'); @@ -38,16 +42,116 @@ const bruToJson = (fileContents) => { return { ver: parsed.ver, - type: parsed.type, - name: parsed.name, - method: parsed.method, - url: parsed.url, - params: parsed.params, - headers: parsed.headers, - body: parsed.body + type: parsed.type || '', + name: parsed.name || '', + method: parsed.method || '', + url: parsed.url || '', + params: parsed.params || [], + headers: parsed.headers || [], + body: parsed.body || {mode: 'none'} } }; +const jsonToBru = (json) => { + const { + ver, + type, + name, + method, + url, + params, + headers, + body + } = json; + + let bru = `ver ${ver} +type ${type} +name ${name} +method ${method} +url ${url} +body-mode ${body.mode} +`; + + if(params && params.length) { + bru += ` +params +${params.map(param => ` ${param.enabled} ${param.key} ${param.value}`).join('\n')} +/params +`; + } + + if(headers && headers.length) { + bru += ` +headers +${headers.map(header => ` ${header.enabled} ${header.key} ${header.value}`).join('\n')} +/headers +`; + } + + if(body.json && body.json.length) { + let jsonText = ''; + let bodyJson = body.json; + if(bodyJson && bodyJson.length) { + bodyJson = bodyJson.trim(); + const safelyParsed = safeParseJson(bodyJson); + + if(safelyParsed) { + jsonText = JSON.stringify(safelyParsed, null, 2); + } else { + jsonText = bodyJson; + } + } + bru += ` +body(type=json) +${indentString(jsonText)} +/body +`; + } + + if(body.graphql && body.graphql.query) { + bru += ` +body(type=graphql) +${indentString(body.graphql.query)} +/body +`; + } + + if(body.text && body.text.length) { + bru += ` +body(type=text) +${indentString(body.text)} +/body +`; + } + + if(body.xml && body.xml.length) { + bru += ` +body(type=xml) +${indentString(body.xml)} +/body +`; + } + + if(body.formUrlEncoded && body.formUrlEncoded.length) { + bru += ` +body(type=form-url-encoded) +${body.formUrlEncoded.map(item => ` ${item.enabled} ${item.key} ${item.value}`).join('\n')} +/body +`; + } + + if(body.multipartForm && body.multipartForm.length) { + bru += ` +body(type=multipart-form) +${body.multipartForm.map(item => ` ${item.enabled} ${item.key} ${item.value}`).join('\n')} +/body +`; + } + + return bru; +}; + module.exports = { - bruToJson + bruToJson, + jsonToBru }; \ No newline at end of file diff --git a/packages/bruno-lang/src/inline-tag.js b/packages/bruno-lang/src/inline-tag.js index 097e2e45..cb7be2d7 100644 --- a/packages/bruno-lang/src/inline-tag.js +++ b/packages/bruno-lang/src/inline-tag.js @@ -24,8 +24,13 @@ const inlineTag = sequenceOf([ everyCharUntil(newLineOrEndOfInput) ]).map(([key, _, val]) => { if(key === 'body-mode') { - key = 'bodyMode'; + return { + body: { + mode: val + } + }; } + return { [key]: val }; }); diff --git a/packages/bruno-lang/src/utils.js b/packages/bruno-lang/src/utils.js index 4f041b7d..38182d3c 100644 --- a/packages/bruno-lang/src/utils.js +++ b/packages/bruno-lang/src/utils.js @@ -7,6 +7,15 @@ const safeParseJson = (json) => { } }; +const indentString = (str) => { + if(!str || !str.length) { + return str; + } + + return str.split("\n").map(line => " " + line).join("\n"); +} + module.exports = { - safeParseJson + safeParseJson, + indentString }; diff --git a/packages/bruno-lang/tests/bru-to-json.spec.js b/packages/bruno-lang/tests/bru-to-json.spec.js new file mode 100644 index 00000000..25dc257d --- /dev/null +++ b/packages/bruno-lang/tests/bru-to-json.spec.js @@ -0,0 +1,92 @@ +const fs = require('fs'); +const path = require('path'); + +const { + jsonToBru +} = require('../src'); + +describe('bruToJson', () => { + it('should convert json file into .bru file', () => { + const request = { + "ver": "1.0", + "type": "http-request", + "name": "Send Bulk SMS", + "method": "GET", + "url": "https://api.textlocal.in/bulk_json?apiKey=secret=&numbers=919988776655&message=hello&sender=600010", + "params": [ + { + "enabled": "1", + "key": "apiKey", + "value": "secret" + }, + { + "enabled": "1", + "key": "numbers", + "value": "998877665" + }, + { + "enabled": "1", + "key": "message", + "value": "hello" + } + ], + "headers": [ + { + "enabled": "1", + "key": "content-type", + "value": "application/json" + }, + { + "enabled": "1", + "key": "accept-language", + "value": "en-US,en;q=0.9,hi;q=0.8" + }, + { + "enabled": "0", + "key": "transaction-id", + "value": "{{transactionId}}" + } + ], + "body": { + "mode": "json", + "json": '{"apikey":"secret","numbers":"+91998877665"}', + "graphql": { + "query": "{\n launchesPast {\n launch_success\n }\n}" + }, + "text": "Hello, there. You must be from the past", + "xml": "back to the ice age", + "formUrlEncoded": [ + { + "enabled": "1", + "key": "username", + "value": "john" + }, + { + "enabled": "0", + "key": "password", + "value": "{{password}}" + } + ], + "multipartForm": [ + { + "enabled": "1", + "key": "username", + "value": "nash" + }, + { + "enabled": "0", + "key": "password", + "value": "governingdynamics" + } + ] + } + }; + + const expectedBruFile = fs.readFileSync(path.join(__dirname, 'fixtures', 'request.bru'), 'utf8'); + const actualBruFile = jsonToBru(request); + + expect(expectedBruFile).toEqual(actualBruFile); + }); +}); + + diff --git a/packages/bruno-lang/tests/inline-tag.spec.js b/packages/bruno-lang/tests/inline-tag.spec.js index 05b5db0a..334568cb 100644 --- a/packages/bruno-lang/tests/inline-tag.spec.js +++ b/packages/bruno-lang/tests/inline-tag.spec.js @@ -76,7 +76,7 @@ body-mode json [{ name: 'Send Bulk SMS' }], [{ method: 'GET' }], [{ url: 'https://api.textlocal.in/bulk_json?apiKey=secret=&numbers=919988776655&message=hello&sender=600010' }], - [{ bodyMode: 'json' }], + [{ body: { mode: 'json' } }], [] ]); }) diff --git a/packages/bruno-lang/tests/parser.spec.js b/packages/bruno-lang/tests/json-to-bru.spec.js similarity index 98% rename from packages/bruno-lang/tests/parser.spec.js rename to packages/bruno-lang/tests/json-to-bru.spec.js index a7e3e6a5..4c7cb830 100644 --- a/packages/bruno-lang/tests/parser.spec.js +++ b/packages/bruno-lang/tests/json-to-bru.spec.js @@ -51,6 +51,7 @@ describe('bruToJson', () => { } ], "body": { + "mode": "json", "json": '{"apikey":"secret","numbers":"+91998877665"}', "graphql": { "query": " {\n launchesPast {\n launch_success\n }\n }" diff --git a/packages/bruno-lang/tests/utils.spec.js b/packages/bruno-lang/tests/utils.spec.js new file mode 100644 index 00000000..618923a7 --- /dev/null +++ b/packages/bruno-lang/tests/utils.spec.js @@ -0,0 +1,28 @@ +const { + safeParseJson, + indentString +} = require('../src/utils'); + +describe('utils', () => { + describe('safeParseJson', () => { + it('should parse valid json', () => { + const input = '{"a": 1}'; + const result = safeParseJson(input); + expect(result).toEqual({ a: 1 }); + }); + + it('should return null for invalid json', () => { + const input = '{"a": 1'; + const result = safeParseJson(input); + expect(result).toBeNull(); + }); + }); + + describe('indentString', () => { + it('correctly indents a multiline string', () => { + const input = "line1\nline2\nline3"; + const expectedOutput = " line1\n line2\n line3"; + expect(indentString(input)).toBe(expectedOutput); + }); + }); +}); \ No newline at end of file