Building a REST API With Feathers.js and SQLite | by Arctype | Apr, 2022

Building a REST API with Feathers.js and SQLite
Image by author

Looking for a way to build a web application with features like authentication, database setup, and authorization without writing a ton of code and configurations? Ever wanted to create a production-ready app in a matter of days?

Believe it or not, it’s possible! This tutorial will show you how to use Feathers.js to create a REST API in minutes. We’ll learn about Feathers.js, implement an example API, and share some thoughts and considerations. Let’s begin.

Feathers is a lightweight web framework for developing real-time apps and REST APIs in JavaScript or TypeScript.

Feathers can interact with any backend technology, supports over a dozen databases, and works with any frontend technology, such as React, VueJS, Angular, and React Native.

Feathers.js is well-known for its ease of use and rapidity of delivery, and extensive documentation. With Feathers, all you need to add a feature is to run a simple command.

This tutorial is a hands-on demonstration. To get started, I assume you have the following:

You will create a movie rental application to illustrate the capabilities of Feathers.js and Arctype database visualization tools. The administrator will generate movies in this program, and authenticated users will be able to rent them. You’ll learn to use Sequelize to correlate tables in Feathers.js, restrict access to specific routes, and link your database to Arctype.

To get started, open your command-line interface and create a folder for this tutorial with the command below:

npm install @feathersjs/feathers --save

Wait for the installation to complete and confirm the installation with the command below:

feathers -V

If everything went well with the installation, you’d see the version number printed out on the console.

With Feathers installed on your computer, create a folder for this application with the command below:

Mkdir RestWithFeathers && RestWithFeathers

Then, generate a new API application with the command below:

feathers generate app

The above command will prompt you to select the configuration for your application. For the demonstration in this tutorial, your selection should look like the screenshot as shown below:

Building a REST API with Feathers.js and SQLite

In the above screenshot, we made the following selections:

  • Selected JavaScript as the preferred programming language
  • Specified the name for the application (movie-rental)
  • Selected src the location for the project boilerplates
  • Selected npm as the package manage
  • Enabled user authentication
  • Selected Eslint to analyze our code
  • Choose a username and password authentication strategy.
  • Selected user as the name for our entity
  • Selected Sequelize as the ORM for the application
  • Selected SQLite as our database
  • Specified movieDB as our database name

Once the selections are completed, the command will generate an express-like project structure. Now let’s look at the folder structure generated by running the above command.

Building a REST API with Feathers.js and SQLite

For this tutorial, we’ll look at once we look at the following:

  • config: Contains the configuration files for the application
  • node_modules: A folder to store the list of installed packages required to run the application.
  • public: Contains the static files that can be served to the client.
  • src: Contains the server code for Feathers.js applications
  • src/hooks: Contains the application custom hooks.
  • src/middleware: Contains Express middleware
  • src/service: Contains our application services
  • src/index.js: The entry file that runs the application
  • src/app.js: Configures our Feathers application
  • src/app.hook.js: Contains hooks that apply to every service
  • src/channels.js: Sets Featherjs event channels
  • test: Contains the test for the application

Now run the server in development mode with the command below:

npm run dev

Running the server in development activates hot reload and console error logging. At this point, the server should be running on port 3030, and a moviedb.sqlite file should be created in your project’s root directory.

A service is an object or instance of a class that implements certain methods. Services provide a consistent, protocol-independent interface for interacting with any data. In Feathers, you just need to run a command, and everything is set up for you to create a service. Create a movie service with the command below:

feathers generate service

The above command will prompt you to select the configurations for your service. Your selection should look like the screenshot as shown below:

Building a REST API with Feathers.js and SQLite

Here, you selected the ORM for your movie table, the service name, the route URL, and enabled authentication on the movie routes. Once those selections are completed, the command will generate a folder structure below in the src/service folder.

πŸ“¦movie
┣ πŸ“œmovie.class.js
┣ πŸ“œmovie.hooks.js
β”— πŸ“œmovie.service.js

In your movie.hook file, Feathers added the code snippet below, which ensures that before the request passes through this route to the movie service, it has to confirm the user’s user access token sent when the user logged in.

before: {
all: [],
find: [ authenticate('jwt') ],
get: [ authenticate('jwt') ],
create: [ hashPassword('password') ],
update: [ hashPassword('password'), authenticate('jwt') ],
patch: [ hashPassword('password'), authenticate('jwt') ],
remove: [ authenticate('jwt') ]
},

Next, create a rental service with the command below:

feathers generate service

The above performs the same operation with that movie service, but this time generates a different folder name and files as shown below:

πŸ“¦ rentals
┣ πŸ“œrentals.class.js
┣ πŸ“œrentals.hooks.js
β”— πŸ“œrentals.service.js

It will also call the jwt authenticate(β€˜jwt’) function in all the routes. Also, the command will generate the respective models for the services you just created with some boilerplates as shown below:

πŸ“¦models
┣ πŸ“œmovie.model.js
┣ πŸ“œrentals.model.js
β”— πŸ“œusers.model.js

With the services and models created, modify the model’s properties to have the required properties for the movie and rentals table. For the movie model, add the following properties to the properties.

title: {
type: DataTypes.STRING,
allowNull: false,
},
producer: {
type: DataTypes.STRING,
allowNull: false,
},
imageURL: {
type: DataTypes.STRING,
allowNull: false,
},
createdAt: { type: DataTypes.DATE, defaultValue: Date.now },
updatedAt: { type: DataTypes.DATE, defaultValue: Date.now },

Then, in the model of the rental, add the following properties.

quantity: {
type: DataTypes.INTEGER,
allowNull: false,
},
createdAt: { type: DataTypes.DATE, defaultValue: Date.now },
updatedAt: { type: DataTypes.DATE, defaultValue: Date.now },

We still need to create an association between the user, movie, and rental model, which brings us to the next section.

Database relationships are associations formed between tables when data is retrieved using join statements. Relationships are often planned using an ERD diagram.

Our application has a user, a movie, and a rental table. The movie is owned by a rental, and a user owns a rental. The most straightforward approach to maintaining track of this data in each database is to establish a relationship between them, saving the table IDs as a foreign key in the tables with which they are related. So let’s go ahead and create a relationship between of three tables. In the models/user.models.jslocate the comments:

// Define associations here
// See https://sequelize.org/master/manual/assocs.html

And add the code snippet below.

const { rentals } = models;
users.hasMany(rentals);

You created a one-to-many relationship with the rentals table in the code snippet. This means that one user can have many rentals.

We then will also add the code below to the models/movie.model.js file.

const { rentals, movie } = models;
movie.belongsToMany(rentals, { through: 'MovieRendtals' });

In the above code snippet, we created a many-to-many relationship between the rentals table, meaning a movie can have multiple rentals. In many-to-many relationships, a junction table is created to track the two tables’ IDs, in this case, MovieRentals.

Lastly, add the code snippet below to the models/rentals.model.js file.

const { users, movie } = models;
rentals.belongsTo(users);
rentals.belongsToMany(movie, { through: 'MovieRentals' });

At this point, the tables now have a relationship with each other. Now you can load the data into the tables when you create or fetch the data from any service. That brings us to hooks in Feathers.

Hooks are pluggable middleware functions that can be registered before, after, or on errors of a service method. You can register a single hook function or create a chain of them to create complex workflows. You’ll create a hook that will load the data associated with each table. In your service/rentals folder, create a get-related.js file and the snippet below:

module.exports = function (options = {}) {
return async (context) => {
const sequelize = context.app.get('sequelizeClient');
const { users, movie } = sequelize.models;
context.params.sequelize = {
include: [{ model: users }, { model: movie }],
raw: false,
};
return context;
};
};

In the above code, the snippet tells Feathers to load users and movie models whenever a movie is rented. Now update your service/rentals/rental.hooks.js file with the code snippet below. Modify the code inside the before object.

all: [authenticate('jwt')],
find: [getRelated()],
get: [getRelated()],
create: [getRelated()],
update: [],
patch: [],
remove: []

Now let’s test the application with Insomnia. We’ll start with the users routes.

Create a user

Create a user on the /users route.

Building a REST API with Feathers.js and SQLite

Authenticate a user

Authenticate a user on the /authentication route.

Building a REST API with Feathers.js and SQLite

Create a movie

Create a movie on the /movie route.

Building a REST API with Feathers.js and SQLite

Rent a movie

Rent a movie on the /rentals route. You’ll specify the userId, movieIdand quantity fields in this route.

Building a REST API with Feathers.js and SQLite

These look good! Now go ahead and test other requests method on each route, like GET, UPDATEand DELETE.

Connect your database to Arctype to view the tables and data created in your application. You can connect to Arctype by following these steps:

  1. Run Arctype
  2. Click on the SQLite tab.
  3. Click on the Choose SQLite File button
  4. Navigate to the project folder and select the moviedb.sqlite file
  5. Test the connection and save the changes

Once your database is connected to Arctype, you’d see the users, movies, rentalsand MovieRentals tables as shown in the screenshot below:

Building a REST API with Feathers.js and SQLite

At this point, your database has successfully been connected to Arctype. You can click on each table to show the data saved in them.

Throughout this tutorial, you’ve explored Feathers.js by building a demo application. You’ve learned how to set up a Feathers.js application, create a service, implement authentication/authorization, create custom hooks, and connect to Arctype.

Now that you’ve gotten this knowledge, how do you intend to use Feathers in your next project? Perhaps you can even add an extra feature to this project by forking or cloning the Github repository.

Leave a Comment