Skip to content

Commit

Permalink
feat(#122): Support parsing of dotenv files
Browse files Browse the repository at this point in the history
  • Loading branch information
helloanoop committed Sep 21, 2023
1 parent 19ca1af commit 1c4c5cc
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
76 changes: 76 additions & 0 deletions packages/bruno-lang/v2/src/dotenvToJson.js
Original file line number Diff line number Diff line change
@@ -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;
44 changes: 44 additions & 0 deletions packages/bruno-lang/v2/tests/dotenvToJson.spec.js
Original file line number Diff line number Diff line change
@@ -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);
});
});

0 comments on commit 1c4c5cc

Please sign in to comment.