forked from extern/bruno
feat: bru lang - parse env files
This commit is contained in:
parent
c3236d4eb1
commit
84bd603e11
@ -138,7 +138,7 @@ const sem = grammar.createSemantics().addAttribute('ast', {
|
|||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
key(chars) {
|
key(chars) {
|
||||||
return chars.sourceString;
|
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||||
},
|
},
|
||||||
value(chars) {
|
value(chars) {
|
||||||
return chars.sourceString ? chars.sourceString.trim() : '';
|
return chars.sourceString ? chars.sourceString.trim() : '';
|
||||||
|
108
packages/bruno-lang/v2/src/envToJson.js
Normal file
108
packages/bruno-lang/v2/src/envToJson.js
Normal file
@ -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;
|
25
packages/bruno-lang/v2/src/jsonToEnv.js
Normal file
25
packages/bruno-lang/v2/src/jsonToEnv.js
Normal file
@ -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;
|
88
packages/bruno-lang/v2/tests/envToJson.spec.js
Normal file
88
packages/bruno-lang/v2/tests/envToJson.spec.js
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
55
packages/bruno-lang/v2/tests/jsonToEnv.spec.js
Normal file
55
packages/bruno-lang/v2/tests/jsonToEnv.spec.js
Normal file
@ -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);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user