Update (7 Oct 2023): Keep a watchout for this experiment for supporting multiple languages on how the request gets stored. If it succeeds, then Bruno can offer flexibility and freedom of choice. Users should never feel constrained and compelled to use only the bru lang
I'll perhaps write a more detailed blog about this decision in a lot more detail later. But here is a decent summary.
I can assure you that I thought through this for months, because I knew that once you design a DSL, its pretty to hard to migrate stuff since we directly write to filesystem. Data format migrations are easier if its a hosted solution where your data is sitting in a database
How complex can it get?
At first glance, when you just think about url, http method, headers, request body, response body, it seems like a simpler problem. But as you expand your needs to store tests, assertions, request variables, response variables, docs it starts getting complicated. See this full blown request example where an api can accept data in multiple formats. Now imagine to represent this in JSON/YAML and keep it readable, I hope you are getting my viewpoint here.
Easy pr reviews via git for collaboration
The goal was not just to write to a file, but to be able to do a PR review flow in git. This meant that the plaint-text representation of the request had to be simple and easily readable enough to be able to do that.Also, simple enough so that you can open the collection folder in a editor (like vscode) and still be able to make changes.
I look forward to the day where it becomes a norm for developers start storing api collection in their source code itself. So that anyone who clones the repo can bring the service up and start playing exploring the api. And athen continue to maintain the api collections just like code.
Lang iterations
The language itself went through many iterations.
- First was break a giant collection json and save it as individual files
- Second attempt was to convert into a dsl (was a bit xmlishy)
- The third attempt that is used today to made it even simpler (jsonishy/groovishy)
@ajaishankar played a crucial role in helping me design the lang.
Why not JSON/YAML ?
Json didn't support multiline strings. Yaml was indentation hell. I wanted something neat, no need for quotes around strings. And lot of nuances, like "how do you represent a key-val paid as disabled in a single line".
Like it was quite nice to go from
headers {
content-type: application/json
accept-language: en-US,en;q=0.9,hi;q=0.8
}
headers:disabled {
transaction-id: {{transactionId}}
}To
headers {
content-type: application/json
accept-language: en-US,en;q=0.9,hi;q=0.8
~transaction-id: {{transactionId}}
}Parser
Bruno DSL is built on top of Ohm
For v1 I used arcsecond parser combinator library by @francisrstokes
For V2, I used ohmjs library by @pdubroy The entire parser that translates .bru files to its json representation is just one single file
Once you wrap you head around it, Ohm is really powerful.
Github issue for reference: #82
