Requirements
node: v18.20.3
Install
yarn install
cd functions && yarn install
Configure Firebase
firebase login
firebase use default
Build (Local)
yarn build
cd functions && yarn build
Run (local)
yarn start
yarn emulate
yarn init:emu
Description: In Nest.js, the architecture is modular and separates concerns across different components to promote maintainability and scalability. Here’s a brief overview of each component and their differences:
Controller:
Purpose: Manages incoming HTTP requests and sends responses to the client.
Role: Acts as the entry point for the application’s routes. It receives the request, processes it (often by delegating to a service), and returns the response.
Usage: Defines endpoints using decorators (e.g., @Get(), @Post()) and handles request routing and response formatting.
Service:
Purpose: Encapsulates the business logic of the application.
Role: Contains methods that implement the core functionality of the application, such as processing data, applying business rules, and managing transactions.
Usage: Called by controllers to perform operations and can also call other services or repositories as needed.
Repository:
Purpose: Manages data access and persistence.
Role: Provides an abstraction layer over the database, handling CRUD operations and queries. It interacts directly with the data source.
Usage: Used by services to perform data operations. In Nest.js, repositories are typically used in conjunction with an ORM (e.g., TypeORM).
Module:
Purpose: Organizes the application into cohesive blocks or units.
Role: Groups related controllers, services, and repositories together. It defines the scope of the components and manages their dependencies.
Usage: A module is defined using the @Module() decorator and specifies which components it includes and what other modules it imports. It helps in keeping the code modular and scalable.
Description: To validate incoming requests in Nest.js, use Data Transfer Objects (DTOs) along with the class-validator library. Here’s a short example related to booking.
Create DTO in booking-models.ts:
import { IsString, IsBoolean } from 'class-validator';
export class CreateBookingDto {
@IsString()
customerName: string;
@IsString()
roomType: string;
@IsBoolean()
isPaid: boolean;
}
Use DTO in booking.controller.ts:
import { Controller, Post, Body, ValidationPipe } from '@nestjs/common';
import { CreateBookingDto } from './booking-models';
import { BookingService } from './booking.service';
@Controller('bookings')
export class BookingController {
constructor(private readonly bookingService: BookingService) {}
@Post()
create(
@Body(ValidationPipe) createBookingDtoBody: CreateBookingDto,
@Query(ValidationPipe) createBookingDtoQuery: CreateBookingDto
) {
return this.bookingService.createBooking(createBookingDto);
}
}
Description: The ConfigRepository service in Nest.js provides methods to manage and retrieve configuration data from the database. Key methods include findDomain(id), findPropertyById(propertyId), findPropertyByTechId(techId), and findAllProperties(), which handle various property and domain configurations. Additionally, it supports updating specific fields like key safe codes and the last refreshed timestamp, ensuring efficient configuration management.
Navigate to the Error Codes File: Open the file located at src/service/common-v2/error/jh-exception-codes.ts.
Add a New Error Code: In the JHErrorCode enum, add a new error code entry.
export enum JHErrorCode {
BOOKING_CREATE_FAILED = "BOOKING_CREATE_FAILED",
}
Navigate to the Exception Parameters File: Open the file located at src/service/common-v2/error/jh-exception-params.ts.
Define the New Error Code Details: Add the details of the new error code in the appropriate object.
[JHErrorCode.BOOKING_CREATE_FAILED]: {
domainName: JHErrorDomain.BOOKING,
message: "Creating booking failed!"
},
Throw the New Exception Code: Now that the new exception code is defined, you can throw it in your code where necessary.
Description: To throw an exception, ensure the exception code is defined, then use the jhException function.
Example:
throw jhException(
JHErrorCode.BOOKING_CREATE_FAILED,
{ techId: propertyConfig.techId, bookingId: masterBookingId },
error
);
Import the Logger:
import { Logger } from 'src/service/common-v2/logger';
Create a Logger Variable:
@Injectable() export class BookingService {
private readonly logger = Logger.getLogger(BookingService);
}
Use the Logger:
this.logger.debug("Debug message", { variable });
this.logger.error("Error message", { variable });
this.logger.info("Info message", { variable });
Description: in the file located at src/service/common-v2/asserts.ts we have some function for assertation like
assertEqual(expected, happened, jhErrorCode, jhErrorParams)
assertNotEquall(expected, happened, jhErrorCode, jhErrorParams)
assertNotNulll(value, jhErrorCode, jhErrorParams)
assertTruel(condition, jhErrorCode, jhErrorParams)
Description: Placing all business logic inside Nest.js services simplifies testing and enhances development. Here's why
Dependency Injection (IoC): Leverages Nest.js's IoC for easy dependency management.
Easier Mocking for Testing: Services can be easily mocked, making unit tests simpler and more isolated.
Organized Code Structure: Separates concerns, keeping controllers focused on requests and responses, and services on business logic.
By following this approach, you ensure a maintainable and testable codebase, enhancing overall development efficiency.
Description: use utilityService.getCurrentDate() Instead of new Date()
Description: soon
Description: soon
Description: soon