Setting Up a FeathersJS App with Joi Validation, Kafka, Zookeeper, Redis, TypeScript, and PostgreSQL

2024-08-20

FeathersJS is a versatile framework for building real-time applications and REST APIs using JavaScript or TypeScript. In this guide, we'll walk through the process of setting up a FeathersJS app with TypeScript, Joi validation, Kafka, Zookeeper, Redis, and PostgreSQL. This combination of technologies allows you to build scalable and maintainable applications with robust validation, messaging, and caching.

Prerequisites

Before we start, ensure that you have the following installed:

Step 1: Set Up the Project

Let's begin by creating a new FeathersJS application.

Create the FeathersJS App

If you haven't already, install the Feathers CLI:

npm install -g @feathersjs/cli

Now, create a new FeathersJS app:

feathers generate app

You'll be prompted to answer some questions. Here's a typical setup:

Once generated, navigate into your project directory:

cd my-feathers-app

Install Required Packages

Next, install the necessary packages for Joi validation, Kafka, Redis, PostgreSQL, and TypeScript types:

npm install @feathersjs/feathers @feathersjs/socketio @feathersjs/express @feathersjs/authentication @feathersjs/authentication-jwt @feathersjs/configuration pg feathers-sequelize sequelize class-transformer class-validator
npm install joi @hapi/joi kafka-node redis --save
npm install --save-dev @types/pg @types/redis typescript

Step 2: Configure TypeScript

Since we're using TypeScript, let's set up the tsconfig.json file.

{
  "compilerOptions": {
    "outDir": "./dist",
    "module": "commonjs",
    "target": "es6",
    "strict": true,
    "esModuleInterop": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "resolveJsonModule": true,
    "types": ["node", "jest"]
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

Create a src directory for your TypeScript files:

mkdir src

Move the generated files into the src directory and update imports as needed.

Step 3: Set Up PostgreSQL with Sequelize

Configure PostgreSQL

First, create a PostgreSQL database:

psql -U postgres
CREATE DATABASE feathers_app;

Install Sequelize

We'll use Sequelize to interact with PostgreSQL. First, install Sequelize:

npm install sequelize pg pg-hstore

Initialize Sequelize

Create a sequelize.ts file in src:

// src/sequelize.ts
import { Sequelize } from 'sequelize';
 
const sequelize = new Sequelize('feathers_app', 'postgres', 'yourpassword', {
  host: 'localhost',
  dialect: 'postgres',
});
 
export default sequelize;

Define a Model

Create a simple user model:

// src/models/user.model.ts
import { DataTypes, Model } from 'sequelize';
import sequelize from '../sequelize';
 
class User extends Model {}
 
User.init(
  {
    id: {
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4,
      primaryKey: true,
    },
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
    },
  },
  {
    sequelize,
    modelName: 'User',
  }
);
 
export default User;

Step 4: Integrate Redis

Redis is often used for caching or as a message broker. Let's set up Redis.

Configure Redis

Create a redis.ts file in src:

// src/redis.ts
import Redis from 'redis';
 
const redisClient = Redis.createClient({
  host: 'localhost',
  port: 6379,
});
 
redisClient.on('connect', () => {
  console.log('Connected to Redis');
});
 
export default redisClient;

Step 5: Set Up Kafka with Zookeeper

Kafka is used for building real-time data pipelines and streaming apps.

Configure Kafka

First, create a kafka.ts file in src:

// src/kafka.ts
import { KafkaClient, Producer, Consumer } from 'kafka-node';
 
const client = new KafkaClient({ kafkaHost: 'localhost:9092' });
 
const producer = new Producer(client);
producer.on('ready', () => console.log('Kafka Producer is connected and ready.'));
 
const consumer = new Consumer(
  client,
  [{ topic: 'feathers-topic', partition: 0 }],
  { autoCommit: true }
);
 
consumer.on('message', (message) => {
  console.log('Kafka message received:', message);
});
 
export { producer, consumer };

Step 6: Implement Joi Validation

Joi is used for data validation. Let's validate the user input for the User model.

Create a Validation Schema

Create a validation.ts file in src:

// src/validation.ts
import Joi from 'joi';
 
export const userSchema = Joi.object({
  email: Joi.string().email().required(),
  password: Joi.string().min(6).required(),
});

Use the Schema in Your Service

Integrate the validation schema in your FeathersJS service:

// src/services/user/user.hooks.ts
import { HookContext } from '@feathersjs/feathers';
import { userSchema } from '../../validation';
 
export const validateUser = async (context: HookContext) => {
  const { data } = context;
  const { error } = userSchema.validate(data);
  if (error) {
    throw new Error(error.details[0].message);
  }
  return context;
};

Add this hook to your user service:

// src/services/user/user.service.ts
import { authenticate } from '@feathersjs/authentication';
import { validateUser } from './user.hooks';
 
export const before = {
  create: [validateUser, authenticate('jwt')],
};

Step 7: Set Up FeathersJS Services

Create a simple user service that interacts with PostgreSQL:

// src/services/user/user.service.ts
import { Service, SequelizeServiceOptions } from 'feathers-sequelize';
import { Application } from '../../declarations';
import User from '../../models/user.model';
 
export class UserService extends Service {
  constructor(options: Partial<SequelizeServiceOptions>, app: Application) {
    super({
      ...options,
      Model: User,
    });
  }
}

Register the service in your app:

// src/services/index.ts
import { Application } from '../declarations';
import { UserService } from './user/user.service';
 
export default function (app: Application): void {
  app.use('/users', new UserService({}, app));
}

Step 8: Running the App

Ensure your PostgreSQL, Redis, and Kafka services are running, then start your FeathersJS app:

npm start

Conclusion

Congratulations! You've set up a FeathersJS application with TypeScript, Joi validation, Kafka, Zookeeper, Redis, and PostgreSQL. This setup provides a solid foundation for building scalable and maintainable applications with real-time capabilities and robust data validation. You can now extend this application to suit your specific needs, whether it's adding more services, implementing complex business logic, or optimizing performance.

Happy coding!