feat(#122): Support parsing of dotenv files

This commit is contained in:
Anoop M D 2023-09-22 00:27:27 +05:30
parent 19ca1af71e
commit 1c4c5cc0c0
2 changed files with 120 additions and 0 deletions

View File

@ -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;

View File

@ -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);
});
});