Scaffold Node.js APIs quickly with Todo-CLI
Tags: node, typescript, todecli, showdev
Published: 2021-12-15 12:21:57

<!-- wp:paragraph -->
<p>Hey, y’all! Hope you're doing great! It's been a while since I’ve posted an article. During this period I spent some time working on a node.js CLI for scaffolding APIs. In this article, I want to introduce you to the tool I created, Tode-CLI.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Why I created the tool?</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>First, I want to give a little insight into why I created the CLI I'm about to tell you about. I love using node.js (with express.js) to create APIs. It’s fast and simple to use.  

<br /><br />
However, I dislike having to create common things like models, controllers(routes), and service files from scratch each time I needed one. Additionally, I dislike the tedious efforts needed to set up authentication in applications that requires some level of authentication/authorization. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This led me to ask the question, “what can I do to avoid this repetition?”. &nbsp;So, I decided to build a simple tool that could automate some of these things for myself.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>After working on the tool, I decided to publish it to <a href="https://www.npmjs.com/package/tode-cli" target="_blank" rel="noreferrer noopener">npm </a>in case someone else might find it useful. Let’s take a closer look at the tool I created.</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Introducing Tode-CLI</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Tode-CLI is a tool for scaffolding node.js APIs. It provides commands to automate the boring stuff – creating models, services, controllers, registering routes. Thus, speeding up your development time.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Tode-CLI comes with an elegant ORM, <a href="https://vincit.github.io/objection.js/" target="_blank" rel="noreferrer noopener">objection.js</a>, built on top of the famous query builder, <a href="https://knexjs.org/" target="_blank" rel="noreferrer noopener">knex.js</a>. This makes interacting with databases a breeze when working with projects created by tode-cli.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The following will explore some features of the CLI.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Features</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In this section, I'll take a quick look at some of the core features of the CLI and give usage examples.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Generate/scaffold a project</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>The tode-cli provides a command to scaffold a project that has a straightforward folder structure. You scaffold a project by running <code>$ npx tode-cli create-project hello-world</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This will generate a project, called <code>hello-world</code>, with the following folder structure:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":1753,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://www.taslangraham.com/wp-content/uploads/2021/12/image-5.png" alt="" class="wp-image-1753"/></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Run <code>npm i</code> to install the node packages, then run <code>npm run dev</code> to serve your app locally. Your app will be served at <code>http://localhost:8080/</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Hitting <code>http://localhost:8080/</code> via a client (web browser, postman, etc) will give the following response:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"id":1712,"sizeSlug":"large","linkDestination":"none"} -->
<figure class="wp-block-image size-large"><img src="https://www.taslangraham.com/wp-content/uploads/2021/12/image-2-edited.png" alt="" class="wp-image-1712"/></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>The response above is showing all the none nested routes within the application. By default, a <code>example</code> route comes with the application. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>Adding a Controller</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In node applications, it is common to use <code>route</code> files to handle the routing in the app.
<br />
However, in a tode-cli generated application we call these files controllers and they are stored in the controllers folder. Future updates may see a complete separation of controllers from routes, similar to what popular tools like Laravel and adonis.js does.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To add a controller to your app you simply run <code>$ npx tode-cli add:controller &lt;controller_name&gt;</code>. This will scaffold a controller(route) file like the following:</p>
<!-- /wp:paragraph -->

```javascript
import { Request, Response, Router } from "express";

module.exports = () => {
  const router = Router();
  /**
   * Create a new Item
   */
  router.post("/", async (req, res) => {
    return res.send('demo/ - POST');
  });

  /**
   * Get all Items
   */
  router.get("/", (req: Request, res: Response) => {
    res.send("demo/  - GET");
  });

  /**
   * Get an Item by Id
   */
  router.get("/:id", (req: Request, res: Response) => {
    res.send("demo/  - GET /id");

  });

  /**
   * Update an Item
   */
  router.patch("/:id", (req: Request, res: Response) => {
    res.send("demo/  - PATCH /id");

  });

  return router;
};
```

<!-- wp:paragraph -->
<p>Here we created a controller named <code>demo</code>. This controller is created with handlers for some basic HTTP request methods such as <code>GET</code>, <code>POST</code>, <code>PATCH</code> on the <code>'/demo'</code> path. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>We can test that our controller is working by hitting <code>http://localhost:8080/demo</code> via a client(web browser, postman, etc). We should get the following response:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":1719,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://www.taslangraham.com/wp-content/uploads/2021/12/image-3.png" alt="" class="wp-image-1719"/></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>If we hit <code>http://localhost:8080</code> again we will see the <code>demo</code> route in our list of routes. As you can see here, tode-cli apps offer a level of self-documentation for the routes within the application.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":1780,"sizeSlug":"full","linkDestination":"none"} -->
<div class="wp-block-image"><figure class="aligncenter size-full"><img src="https://www.taslangraham.com/wp-content/uploads/2021/12/image-6.png" alt="" class="wp-image-1780"/></figure></div>
<!-- /wp:image -->

<!-- wp:heading {"level":3} -->
<h3>Models</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Models are classes that represent a table in your database. You use methods on the model to perform queries on the table it represents via an easy-to-use ORM, <a href="https://vincit.github.io/objection.js/" target="_blank" rel="noreferrer noopener">Objection.js</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>To create a model you run the command <code>$ npx tode-cli add:model &lt;model_name&gt;</code>. You'll get a generated model like the following:</p>
<!-- /wp:paragraph -->

```javascript
import BaseModel from "../BaseMode";

export class User  extends BaseModel {
  // Name of table that this model maps back to
  // Table name is the only required property.
  public static tableName = 'ENTER_TABLE_NAME';
  // Example property
  public foo!: string;

  // Add other table fields (columns) as properties to access them via the model

  // Define the relations to other models.
  // READ MORE at https://vincit.github.io/objection.js/guide/relations.html
  public static relationMappings = () => ({
    // specify relation with other modules
  })

}
```

<!-- wp:paragraph -->
<p>In the above, I generated a model called <code>User</code>. Models on have one required property, <code>tableName</code>, which holds the name of the database table that the model represents. You can perform a query to fetch all users in your database table using <code>await User.query()</code>. Read more about objection.js' queries <a href="https://vincit.github.io/objection.js/guide/query-examples.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>The static method <code>relationMappings</code> is where you define your model's relationship with other models - basically representing your database relationships. Read more about objection.js' relationships <a href="https://vincit.github.io/objection.js/guide/relations.html" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Note: To use your models to perform queries you'll first need to set up a database connection to the database with your tables. Read more <a href="https://github.com/taslangraham/tode-cli#configuring-database-connection" target="_blank" rel="noreferrer noopener">here</a>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Services</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Service files contain your business logic. To create a service you run the command <code>$ npx tode add:service &lt;service_name&gt;</code>. When you create a service, a file will be generated like the following.</p>
<!-- /wp:paragraph -->

```javascript
import { ServiceReponse } from "../../config/constants";

class UserService {
  private _foo = "foo";

  constructor() {
    //
  }

  get foo() {
    return this._foo;
  }

  set foo(val: string) {
    this._foo = val;
  }

  public foobar() {
    //
  }
}

const UserService = new UserService();

export { UserService };
```

<!-- wp:paragraph -->
<p>The above is the generated file for a service called <code>UserService</code>.  You can then add methods to perform any logic inside this file. You'll then call these methods from within a controller or another service. Services are also where you utilize your Models to perform database queries where necessary.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Authentication</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Authentication is an essential part of most applications these days. With Tode-Cli you can integrate basic JSON Web Token (JWT) based authentication in your application by running a single command, <code>$ npx tode-cli add:auth</code>.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This command will create the following:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Knex Migration to create a <code>Users</code> table in your database</li><li>Login functionality which you can customise</li><li>Registration functionality which you can customize</li><li>Auth middleware which you can use on protected routes</li><li>Login route - <code>/auth/login</code></li><li>Registration route - <code>/auth/register</code></li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>All you'll need to do afterward is create the users table in your database by executing the migration file that was created. To do this, run the command  <code>$ npx knex migrate:latest</code>. Now authentication is fully integrated.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p></p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Technologes used</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Tode-CLI was developed with the following:</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>TypeScript</li><li><a href="https://oclif.io/" target="_blank" rel="noreferrer noopener">OCLIF </a>- an open source framework for building command line interfaces (CLI) in Node.js.</li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>We've covered some of the core features of Tode-CLI. I first created this tool for my personal use. I hope someone else finds it useful. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>You can have a deeper dive into the docs and configurations <a href="https://github.com/taslangraham/tode-cli#readme" target="_blank" rel="noreferrer noopener">here</a>. Feel free to try it out. Don't hesitate to report any issues you come across. I aim to improve the CLI as time goes by. </p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Thanks for reading, and until next time! <em>Think, Learn, Create, Repeat!</em></p>
<!-- /wp:paragraph -->