feat: bru lang - supporting ~ @ identifiers

This commit is contained in:
Anoop M D 2023-02-05 23:13:18 +05:30
parent 84bd603e11
commit a0cb53445f
5 changed files with 127 additions and 223 deletions

View File

@ -24,9 +24,9 @@ const {
*
*/
const grammar = ohm.grammar(`Bru {
BruFile = (meta | http | querydisabled | query | headersdisabled | headers | bodies | varsandassert | script | tests | docs)*
BruFile = (meta | http | query | headers | bodies | varsandassert | script | tests | docs)*
bodies = bodyjson | bodytext | bodyxml | bodygraphql | bodygraphqlvars | bodyforms
bodyforms = bodyformurlencodeddisabled | bodyformurlencoded | bodymultipartdisabled | bodymultipart
bodyforms = bodyformurlencoded | bodymultipart
nl = "\\r"? "\\n"
st = " " | "\\t"
@ -59,18 +59,13 @@ const grammar = ohm.grammar(`Bru {
trace = "trace" dictionary
headers = "headers" dictionary
headersdisabled = "headers:disabled" dictionary
query = "query" dictionary
querydisabled = "query:disabled" dictionary
varsandassert = vars | varsdisabled | varslocal | varslocaldisabled | assert | assertdisabled
varsandassert = vars | varslocal | assert
vars = "vars" dictionary
varsdisabled = "vars:disabled" dictionary
varslocal = "vars:local" dictionary
varslocaldisabled = "vars:local:disabled" dictionary
assert = "assert" dictionary
assertdisabled = "assert:disabled" dictionary
bodyjson = "body:json" st* "{" nl* textblock tagend
bodytext = "body:text" st* "{" nl* textblock tagend
@ -79,25 +74,30 @@ const grammar = ohm.grammar(`Bru {
bodygraphqlvars = "body:graphql:vars" st* "{" nl* textblock tagend
bodyformurlencoded = "body:form-urlencoded" dictionary
bodyformurlencodeddisabled = "body:form-urlencoded:disabled" dictionary
bodymultipart = "body:multipart-form" dictionary
bodymultipartdisabled = "body:multipart-form:disabled" dictionary
script = "script" st* "{" nl* textblock tagend
tests = "tests" st* "{" nl* textblock tagend
docs = "docs" st* "{" nl* textblock tagend
}`);
const mapPairListToKeyValPairs = (pairList = [], enabled = true) => {
const mapPairListToKeyValPairs = (pairList = []) => {
if(!pairList.length) {
return [];
}
return _.map(pairList[0], pair => {
const key = _.keys(pair)[0];
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: key,
value: pair[key],
enabled: enabled
name,
value,
enabled
};
});
};
@ -143,6 +143,27 @@ const sem = grammar.createSemantics().addAttribute('ast', {
value(chars) {
return chars.sourceString ? chars.sourceString.trim() : '';
},
textblock(line, _1, rest) {
return [line.ast, ...rest.ast].join('\n');
},
textline(chars) {
return chars.sourceString;
},
textchar(char) {
return char.sourceString;
},
nl(_1, _2) {
return '';
},
st(_) {
return '';
},
tagend(_1 ,_2) {
return '';
},
_iter(...elements) {
return elements.map(e => e.ast);
},
meta(_1, dictionary) {
return {
meta: mapPairListToKeyValPair(dictionary.ast)
@ -209,21 +230,11 @@ const sem = grammar.createSemantics().addAttribute('ast', {
query: mapPairListToKeyValPairs(dictionary.ast)
};
},
querydisabled(_1, dictionary) {
return {
query: mapPairListToKeyValPairs(dictionary.ast, false)
};
},
headers(_1, dictionary) {
return {
headers: mapPairListToKeyValPairs(dictionary.ast)
};
},
headersdisabled(_1, dictionary) {
return {
headers: mapPairListToKeyValPairs(dictionary.ast, false)
};
},
bodyformurlencoded(_1, dictionary) {
return {
body: {
@ -231,13 +242,6 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
bodyformurlencodeddisabled(_1, dictionary) {
return {
body: {
formUrlEncoded: mapPairListToKeyValPairs(dictionary.ast, false)
}
};
},
bodymultipart(_1, dictionary) {
return {
body: {
@ -245,13 +249,6 @@ const sem = grammar.createSemantics().addAttribute('ast', {
}
};
},
bodymultipartdisabled(_1, dictionary) {
return {
body: {
multipartForm: mapPairListToKeyValPairs(dictionary.ast, false)
}
};
},
bodyjson(_1, _2, _3, _4, textblock, _5) {
return {
body: {
@ -293,42 +290,25 @@ const sem = grammar.createSemantics().addAttribute('ast', {
},
vars(_1, dictionary) {
const vars = mapPairListToKeyValPairs(dictionary.ast);
_.each(vars, (val) => { val.local = false; });
_.each(vars, (v) => {
let name = v.name;
if (name && name.length && name.charAt(0) === "@") {
v.name = name.slice(1);
v.local = true;
} else {
v.local = false;
}
});
return {
vars
};
},
varsdisabled(_1, dictionary) {
const vars = mapPairListToKeyValPairs(dictionary.ast, false);
_.each(vars, (val) => { val.local = false; });
return {
vars
};
},
varslocal(_1, dictionary) {
const varsLocal = mapPairListToKeyValPairs(dictionary.ast);
_.each(varsLocal, (val) => { val.local = true; });
return {
vars: varsLocal
};
},
varslocaldisabled(_1, dictionary) {
const varsLocal = mapPairListToKeyValPairs(dictionary.ast, false);
_.each(varsLocal, (val) => { val.local = true; });
return {
vars: varsLocal
};
},
assert(_1, dictionary) {
return {
assert: mapPairListToKeyValPairs(dictionary.ast)
};
},
assertdisabled(_1, dictionary) {
return {
assert: mapPairListToKeyValPairs(dictionary.ast, false)
};
},
script(_1, _2, _3, _4, textblock, _5) {
return {
script: outdentString(textblock.sourceString)
@ -343,27 +323,6 @@ const sem = grammar.createSemantics().addAttribute('ast', {
return {
docs: outdentString(textblock.sourceString)
};
},
textblock(line, _1, rest) {
return [line.ast, ...rest.ast].join('\n');
},
textline(chars) {
return chars.sourceString;
},
textchar(char) {
return char.sourceString;
},
nl(_1, _2) {
return '';
},
st(_) {
return '';
},
tagend(_1 ,_2) {
return '';
},
_iter(...elements) {
return elements.map(e => e.ast);
}
});

View File

@ -53,36 +53,30 @@ const jsonToBru = (json) => {
`;
}
if(query && query.length && enabled(query).length) {
bru += `query {
${indentString(enabled(query).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(query && query.length) {
bru += 'query {';
if(enabled(query).length) {
bru += `\n${indentString(enabled(query).map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
`;
if(disabled(query).length) {
bru += `\n${indentString(disabled(query).map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
bru += '\n}\n\n';
}
if(query && query.length && disabled(query).length) {
bru += `query:disabled {
${indentString(disabled(query).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(headers && headers.length) {
bru += 'headers {';
if(enabled(headers).length) {
bru += `\n${indentString(enabled(headers).map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
`;
}
if(disabled(headers).length) {
bru += `\n${indentString(disabled(headers).map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
if(headers && headers.length && enabled(headers).length) {
bru += `headers {
${indentString(enabled(headers).map(header => `${header.name}: ${header.value}`).join('\n'))}
}
`;
}
if(headers && headers.length && disabled(headers).length) {
bru += `headers:disabled {
${indentString(disabled(headers).map(header => `${header.name}: ${header.value}`).join('\n'))}
}
`;
bru += '\n}\n\n';
}
if(body && body.json && body.json.length) {
@ -109,52 +103,42 @@ ${indentString(body.xml)}
`;
}
if(body && body.formUrlEncoded && enabled(body.formUrlEncoded).length) {
bru += `body:form-urlencoded {
${indentString(enabled(body.formUrlEncoded).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(body && body.formUrlEncoded) {
bru += `body:form-urlencoded {`;
if(enabled(body.formUrlEncoded).length) {
bru += `\n${indentString(enabled(body.formUrlEncoded).map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
`;
if(disabled(body.formUrlEncoded).length) {
bru += `\n${indentString(disabled(body.formUrlEncoded).map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
bru += '\n}\n\n';
}
if(body && body.formUrlEncoded && disabled(body.formUrlEncoded).length) {
bru += `body:form-urlencoded:disabled {
${indentString(disabled(body.formUrlEncoded).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(body && body.multipartForm) {
bru += `body:multipart-form {`;
if(enabled(body.multipartForm).length) {
bru += `\n${indentString(enabled(body.multipartForm).map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
`;
}
if(disabled(body.multipartForm).length) {
bru += `\n${indentString(disabled(body.multipartForm).map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
if(body && body.multipartForm && enabled(body.multipartForm).length) {
bru += `body:multipart-form {
${indentString(enabled(body.multipartForm).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
`;
}
if(body && body.multipartForm && disabled(body.multipartForm).length) {
bru += `body:multipart-form:disabled {
${indentString(disabled(body.multipartForm).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
`;
bru += '\n}\n\n';
}
if(body && body.graphql && body.graphql.query) {
bru += `body:graphql {
${indentString(body.graphql.query)}
}
`;
bru += `body:graphql {\n`;
bru += `${indentString(body.graphql.query)}`;
bru += '\n}\n\n';
}
if(body && body.graphql && body.graphql.variables) {
bru += `body:graphql:vars {
${indentString(body.graphql.variables)}
}
`;
bru += `body:graphql:vars {\n`;
bru += `${indentString(body.graphql.variables)}`
bru += '\n}\n\n';
}
if(vars && vars.length) {
@ -163,53 +147,39 @@ ${indentString(body.graphql.variables)}
const varsLocalEnabled = _.filter(vars, (v) => v.enabled && v.local);
const varsLocalDisabled = _.filter(vars, (v) => !v.enabled && v.local);
bru += `vars {`;
if(varsEnabled.length) {
bru += `vars {
${indentString(varsEnabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
}
`;
}
if(varsDisabled.length) {
bru += `vars:disabled {
${indentString(varsDisabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
}
`;
bru += `\n${indentString(varsEnabled.map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
if(varsLocalEnabled.length) {
bru += `vars:local {
${indentString(varsLocalEnabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
}
bru += `\n${indentString(varsLocalEnabled.map(item => `@${item.name}: ${item.value}`).join('\n'))}`;
}
`;
if(varsDisabled.length) {
bru += `\n${indentString(varsDisabled.map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
if(varsLocalDisabled.length) {
bru += `vars:local:disabled {
${indentString(varsLocalDisabled.map(item => `${item.name}: ${item.value}`).join('\n'))}
}
`;
bru += `\n${indentString(varsLocalDisabled.map(item => `~@${item.name}: ${item.value}`).join('\n'))}`;
}
bru += '\n}\n\n';
}
if(assert && enabled(assert).length) {
bru += `assert {
${indentString(enabled(assert).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(assert && assert.length) {
bru += `assert {`;
`;
}
if(enabled(assert).length) {
bru += `\n${indentString(enabled(assert).map(item => `${item.name}: ${item.value}`).join('\n'))}`;
}
if(assert && disabled(assert).length) {
bru += `assert:disabled {
${indentString(disabled(assert).map(item => `${item.name}: ${item.value}`).join('\n'))}
}
if(disabled(assert).length) {
bru += `\n${indentString(disabled(assert).map(item => `~${item.name}: ${item.value}`).join('\n'))}`;
}
`;
bru += '\n}\n\n';
}
if(script && script.length) {
@ -235,7 +205,6 @@ ${indentString(docs)}
`;
}
return stripLastLine(bru);
};

View File

@ -101,8 +101,8 @@ headers {
it("should parse disabled headers", () => {
const input = `
headers:disabled {
content-type: application/json
headers {
~content-type: application/json
}`;
const output = parser(input);

View File

@ -5,26 +5,20 @@ meta {
}
get {
url: https://api.textlocal.in/send/
url: https://api.textlocal.in/send
body: json
}
query {
apiKey: secret
numbers: 998877665
}
query:disabled {
message: hello
~message: hello
}
headers {
content-type: application/json
Authorization: Bearer 123
}
headers:disabled {
transaction-id: {{transactionId}}
~transaction-id: {{transactionId}}
}
body:json {
@ -47,19 +41,13 @@ body:xml {
body:form-urlencoded {
apikey: secret
numbers: +91998877665
}
body:form-urlencoded:disabled {
message: hello
~message: hello
}
body:multipart-form {
apikey: secret
numbers: +91998877665
}
body:multipart-form:disabled {
message: hello
~message: hello
}
body:graphql {
@ -81,26 +69,14 @@ body:graphql:vars {
vars {
token: $res.body.token
}
vars:disabled {
petId: $res.body.id
}
vars:local {
orderNumber: $res.body.orderNumber
}
vars:local:disabled {
transactionId: $res.body.transactionId
@orderNumber: $res.body.orderNumber
~petId: $res.body.id
~@transactionId: $res.body.transactionId
}
assert {
$res.status: 200
}
assert:disabled {
$res.body.message: success
~$res.body.message: success
}
script {

View File

@ -6,7 +6,7 @@
},
"http": {
"method": "get",
"url": "https://api.textlocal.in/send/",
"url": "https://api.textlocal.in/send",
"body": "json"
},
"query": [{
@ -89,18 +89,18 @@
"local": false,
"enabled": true
},
{
"name": "petId",
"value": "$res.body.id",
"local": false,
"enabled": false
},
{
"name": "orderNumber",
"value": "$res.body.orderNumber",
"local": true,
"enabled": true
},
{
"name": "petId",
"value": "$res.body.id",
"local": false,
"enabled": false
},
{
"name": "transactionId",
"value": "$res.body.transactionId",