As software engineers, we use tools built by other devs dozens of times a day. Personally, I use over 15 VS Code extensions. Until my team and I set out to build GraphQuill, I didn't have the slightest clue about the process of developing and publishing an extension. It's been a fun and worthwhile experience working within the VS Code extension space, so when my team and I got together to discuss releasing GraphQuill, I insisted we include a behind the scenes look at the development process and what challenged/excited us throughout.
GraphiQL, GraphQL's in-browser API explorer, is amazing, but the fact remains that it lives outside the coding window. As a result, I need two windows open while I'm working on my GraphQL app: one window for coding, and one window for testing out different queries in the API. This is necessary whether I'm working on my front-end code requesting API data, or modifying my schema or resolver setup in the API itself. On my laptop, I either have to use a split screen or flip back and forth between the two windows. If I have a two-monitor setup, it's a little less disruptive, but I still lose my spot in my code constantly looking from one screen to the other. Either way, it puts a little bit of a funk in my flow.
With GraphQuill, our basic idea was to give devs working on GQL projects a quicker and easier way to test their queries without having to leave VS Code. As we thought about what this might look like, our thoughts quickly turned to quokka, a tool that runs your code for you and prints the result to an output channel in the VS Code terminal. Everyone on our team uses it while building apps to double check that pieces of our code, or even entire files are doing what we expect them to without having to look to our browsers or re-compile and run our code. This was the bar we set for GraphQuill.
To achieve our goal, we broke the tasks down into five sections:
- Run the user's server with their API
- Enable devs to write their queries in line with the rest of their code
- Efficiently parse the queries from the code
- Listen to the current file for changes to know when to query the API
- Actually querying the API and printing the results to the VS Code terminal
We were able to accomplish this using Node.js and VS Code's extension API.
For simplicity and to allow for some customization, we created a GraphQuill config file to allow users to specify the path to their server file and the exposed port number. From there we checked to see if their server was already running, and spawned a Node child process to start it up if it wasn't. One other thing we added for convenience is a command to create the GraphQuill config file with defaults that we've set, and comments to help users decide how to configure the options.
Next, we needed to separate queries from the rest of the code. To accomplish this, we parsed the code for instances of the string "graphquill" and then used a stack to track open parentheses to identify where queries began and ended. After parsing out all queries within a file, to avoid sending requests that would error out in the API, we validated that all braces, brackets, and parentheses were balanced using another stack.
With the ability to parse queries out of a file and validate them, we needed to determine when to parse, validate, and send them to the API. Thankfully, the VS Code API offers multiple ways to do this. Quokka listens for individual key presses, but since we're actually querying an API that is presumably pulling data from a database, we decided to listen for file saves to give users some control in when the queries were sent. We were able to do this with the workspace.onDidSaveTextDocument event. As a last guard against overloading the server/database (and knowing the key-mashing habits of many developers), we debounced our query function so that it didn't send a new request if a file was saved rapidly in succession.
Next came actually sending the queries off to the API and printing the responses to the GraphQuill output channel in VS Code. Here we leveraged Node's async/await syntax to send concurrent requests and wait for all responses to resolve before printing to the output channel.
Overall, this was a really fun project to work on, and we hope it proves to be a useful tool for many an engineer. The code is open source on GitHub, and can be downloaded from the VS Code Extension Marketplace. We just released a beta version and are looking for people to test it out and submit any issues they find so we can continue to make it a better tool.