Enhance API Routes and OpenAPI
by Simon MacDonald
Let’s give it a try.
First, install the Begin CLI. Next, let’s create a new Enhance application by running the following commands:
begin new book-tracker cd book-tracker
When you open the applications directory, you will see a file system that looks like this:
app └── pages └── index.html
That’s a pretty bare-bones application, so let’s add to it.
We have to decide what the object of our application will be. Since I love books, let’s build a site to track all of the books I’ve bought that I haven’t had time to read yet.
begin generate scaffold Books title:string \ author:string start_date:date finish_date:date --openapi
If we look at the file system for the project now, you will see some differences:
app ├── api │ └── books │ ├── $id │ │ └── delete.mjs │ └── $id.mjs ├── elements │ └── enhance-*.mjs ├── models │ └── openapi │ │ └── book.mjs │ └── schemas │ │ └── book.mjs │ └── books.mjs └── pages ├── books │ └── $id.mjs ├── books.mjs └── index.html
Whoa, the scaffold command generated a lot of code for us. In broad strokes here’s what scaffold has done.
app/api directory scaffold has added three files to handle the following API routes:
app/api/books.mjs - GET /books # list all books - POST /books # create new book app/api/books/$id.mjs - GET /books/$id # read one book - POST /books/$id # update a book app/api/books/$id/delete.mjs - POST /books/$id/delete # delete a book
All GET requests return JSON, while POST requests return JSON if the
content-type header is set to
application/json or it will send a redirection response if the
application/x-www-form-urlencoded, which is the case when you do a form post.
app/elements folder contains stubs that point to re-usable form elements from the
enhance-dev/form-elements package. These custom elements are intended to get you up and running quickly, but we fully expect you to build your own amazing components.
Are you intimidated by NoSQL databases and worried about implementing the wrong access patterns? Fear not. Scaffold has created an easy-to-digest data access wrapper in
app/models/books.mjs, which handles communication between your application and DynamoDB. This lets you focus on writing your application without worrying about the persistence layer.
Scaffold also creates a couple of bare-bones pages to view your list of books (
app/pages/books.mjs) and get detailed information about a single book (
app/pages/books/$id.mjs). These pages are intended to be a starting point for your user interface.
The key takeaways from these stubs are how to retrieve data from the store and respond to problems from form submission.
Now that we have the basis of our application, let’s test it locally by running the following command:
Open a browser tab to http://localhost:3333/books and click on the
New book link to reveal the new book form. Fill out the form with some information about a book you’ve recently read. I’m will use the excellent Engineering Management for the Rest of Us by Sarah Drasner for my example.
The example seems straightforward, but what is happening behind the scenes?
- The user fills out the new book form and clicks the “Save” button.
- The browser does a form POST to
/booksto create a new book.
app/api/books.mjsreceives the request and uses our database model to persist the book information.
postmethod redirects the browser to
app/api/books.mjsis invoked and it retrieves the list of books from our database, which then returns this data to our user interface layer at
- Our UI layer renders a list of books.
That’s great, but what if I want to skip the user interface and interact directly with the API layer? We could figure out the cURL commands, but there must be an easier way, and that’s where Open API comes in.
OpenAPI is the most broadly adopted industry standard for describing APIs.
The OpenAPI Specification allows the description of a remote API accessible through HTTP. When you pass the
--openapi option to scaffold, it will automatically create this specification under
app/models/openapi and add a plugin to generate Open API routes to test your API.
The routes are:
GET /openapiwhich lists all the Open API routes you’ve generated
GET /openapi/$idwhich will only show the routes for the one tag, for example
Benefits of Open API
The first and foremost benefit of having an Open API specification is that your API is documented. By going to the
http://localhost:3333/openapi/books route you will be presented with this UI.
Which is slightly easier to digest than digging into the
app/api directory to see which routes are available. Expanding the
GET /books route will show you what type of API response to expect when you hit this route.
However, my favorite part is trying out the API directly from this interface. Click on the “Try it Now” button and then “Execute”. This will invoke the
GET /books route, and you will be able to see the JSON response and response headers. As a bonus, it will give you the cURL command, so you don’t need to figure out all the options yourself.
Scaffold is a powerful command that lets you start building your application quickly. To summarize it:
- Creates API routes that support both JSON and URL Form Encoding.
- It makes an OpenAPI file to enable you to explore the API.
- Writes the database access layer code.
Have you tried out the scaffold command? Let us know what you think on Discord or Mastodon.