forked from extern/bruno
feat: bru lang - supporting ~ @ identifiers
This commit is contained in:
parent
84bd603e11
commit
a0cb53445f
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user