Ready to Go Nest is a versatile Nest.js repository that equips your projects with essential features to accelerate development and enhance functionality. Whether you're building a web application, API, or any other Nest.js-based project, this repository provides you with a solid foundation.
Ready to Go Nest includes a custom Winston logger that offers the following capabilities:
- Logging of errors and events
- File-based log storage for easy troubleshooting
The built-in exception filter ensures robust error handling, making it easier to catch and manage exceptions in your Nest.js application.
- Email notifications for critical 500 errors
- Unified Shape of Response
- Nice Validation Object Response
Streamline your database setup and management with the included seeding and migrations features. These features allow you to:
- Easily populate your database with initial data using seeding.
- Keep your database schema up to date with migrations, making it simple to evolve your application over time.
Ready to Go Nest simplifies data retrieval with the powerful "Query Filter" feature, allowing you to filter, search, sort, and paginate data effortlessly. Here's how you can harness this feature:
-
Filter by Columns: Easily filter data based on specific columns or fields. You can narrow down results to meet your application's requirements.
-
Search: Implement a search functionality that allows users to find records by providing search keywords. This feature enhances user experience and data accessibility.
-
Sort: Sort data in ascending or descending order based on one or more columns. Sorting ensures that data is presented in a meaningful and organized way.
-
Paginate: Implement pagination to display large datasets in manageable chunks. Users can navigate through pages to view additional data without overwhelming the interface.
The "Unique Constraint Custom Validator" is a versatile and widely used feature that ensures the uniqueness of data within your application. It's a valuable tool in preventing duplicate entries in databases and maintaining data integrity.
Integrate Bull to handle email sending efficiently. This feature allows you to:
- Queue and process email sending tasks asynchronously, preventing delays in your application's response time.
- Manage email delivery with ease, including retries and error handling.
Ready to Go Nest offers comprehensive authentication options, including:
- JWT-based user authentication
- Google OAuth2 authentication
- User registration and password reset functionality
Effortlessly manage project configuration with a pre-configured setup. Customize and adapt settings to suit your specific needs.
Ready to Go Nest includes Swagger integration to simplify the documentation of your API endpoints. Swagger provides an interactive and user-friendly interface for exploring and testing your API. Here's how to use Swagger in your project:
To get started with Ready to Go Nest, follow these steps:
-
Clone this repository to your local machine.
-
Configure your project's settings by editing the provided configuration files.
-
Install the necessary dependencies using npm or yarn:
npm install # or yarn install
Ready to Go Nest includes a custom Winston logger that provides flexibility for adding different transports for your log messages. If you want to log messages to the command line (CLI), you can easily add a new transport. Here's how you can do it:
// Add a new transport for logging in src/configs/logger.config
// by simply pushing you new logging transport to the loggerTransports array
loggerTransports.push(
new transports.Console(), // custom winston transport
);
// In main.ts override nest logger to use winston logger
import { loggerOptions } from './configs/logger.config';
const app = await NestFactory.create(AppModule, {
logger: WinstonModule.createLogger(loggerOptions),
});
// Now you can use the logger by injecting Nest Logger
logger.info('This is an info message.');
logger.error('This is an error message.');
// Customize the transport and formatting options as per your requirements.
Modify the global exception filter to fits your needs in /src/exception/all.filter.ts
To apply pending migrations and update your database schema, use the following command:
npm run migration:run
To create a new migration file based on changes in your application's models or schema, use the following command:
npm run migration:generate -- src/database/migrations/MigrationName
To revert the last applied migration and roll back changes to your database schema, use the following command:
npm run migration:revert
-
Open your terminal and navigate to your project's root directory.
-
To create a new seed file, run the following command, replacing
src/path/to/seeds/folder
with the actual path where you want to create the seed file andMySeedFile
with your desired filename:
npm run seed:create -- -name=src/path/to/seeds/folder/MySeedFile.ts
- Run the seeder:
npm run seed:run
- Decorate the query object by using the FilterDecorator
@Get('/')
async getUsers(@FilterDecorator() userQueryFilterDto: UserQueryFilterDto) {
return formatResponse(
HttpStatus.OK,
'users retrieved successfully',
await this.userService.getUsers(userQueryFilterDto),
);
}
- Inject filter service and call the get generic method providing the desired entity to be filtered on.
constructor(private readonly filterService: FilterService) {}
async getUsers(userQueryFilterDto: UserQueryFilterDto) {
return await this.filterService.get<User>(
userQueryFilterDto,
this.userRepository,
{
// options go here
},
);
}
- Implement a userQueryFilterDto that extends the filterDto
import { QueryFilterDto } from 'src/modules/filter';
export class UserQueryFilterDto extends QueryFilterDto {
@IsOptional()
@IsNotEmpty()
loginStrategy: string;
}
The "Conditions" object functions similarly to adding a "WHERE" statement in your queries. For example let's assume that you want to retrieve all users that has the loginStrategy of 'google':
- Simply add the conditions object to the filter service
conditions: {
loginStrategy: userQueryFilterDto.loginStrategy,
// add more conditions
},
- Use the following url
http://localhost:3001/v1/user?loginStrategy=jwt
Searching becomes incredibly simple, all you need to do is:
- add the searchableColumns:
{
searchableColumns: ['username', 'email'],
}
- Use the following url:
http://localhost:3001/v1/user?search=majd
- add the sortableColumns:
{
sortableColumns: ['username', 'email', 'createdAt'],
}
- Use the following url:
http://localhost:3001/v1/user?sortBy=createdAt:DESC
You can also sort either by DESC or ASC
To enable filtering on values, you can configure the filterableColumns
object in your project. This configuration defines which columns are filterable and which filtering operators can be used on each column. Here's an example configuration:
{
filterableColumns: {
name: [FilterOperator.LIKE, FilterOperator.EQ],
createdAt: [FilterOperator.GT]
},
}
Once you've configured the filterableColumns, you can incorporate filtering into your queries. Here's an example of how to apply filtering when retrieving data:
http://localhost:3001/v1/user?filter.created_at=$gt:2020-01-01&filter.username=Majd
In some cases, you may notice that the 'Conditions' and 'Filter' options appear to have similar functions. However, they serve distinct purposes:
-
"Conditions Option:" Use the 'Conditions' option when you need to manually add specific conditions to your queries, typically when you want to apply filters that are not based on query parameters. This option gives you fine-grained control over how you filter data.
-
"Filterable Columns Option:" On the other hand, the 'Filterable Columns' option empowers users to decide which columns to filter on and how to filter them. For instance, if a user has a list of posts, it's more convenient to provide an API specialized in returning a user's posts rather than having them add query parameters like '?user.id=1' manually.
To utilize the "Select" option, you can provide an array of field names that you wish to include in the query result. For instance:
{
selectFields: ['username', 'id'],
}
To enable pagination, you can specify the paginate
option in your queries. This option includes two properties:
limit
: Defines the maximum number of records to retrieve per page. In the example configuration below, we've set the limit to 10, which means each page will display a maximum of 10 records.skip
: Indicates the number of records to skip before starting to retrieve data. This is particularly useful when you want to skip a certain number of records at the beginning of a query result. For example, if you setskip
to 10, the query will skip the first 10 records and start retrieving data from the 11th record onward.
{
paginate: {
limit: 10,
skip: 10,
},
}
http://localhost:3001/user?page=2&limit=1
To retrieve data along with related entities, you can specify the withRelations
option in your queries. This option accepts an array of related entities that you want to include in the query result. For example:
{
// usually password resets should not be returned in response if you are testing
// the code below on the template just remove the @Exclude in password-reset.entity.ts
withRelations: ['passwordResets'];
}
You can also incorporate relationships into any of the options mentioned above. Let's explore a comprehensive example to illustrate this.
{
sortableColumns: ['passwordResets.reset_password_expire'],
withRelations: ['passwordResets'],
},
And then:
http://localhost:3001/user?sortBy=passwordResets.reset_password_expire:ASC
You can simply import MailModule and the inject the mailService:
constructor(private readonly mailService: MailService) {}
or you can create you own process using bull and inject the mailService inside the processor:
@Processor('error')
export class ErrorMailConsumer {
constructor(private readonly mailService: MailService) {}
@Process('internal_error_occurred')
async sendException(job: Job<IMailError>) {
const error: IMailError = job.data;
await this.mailService.sendException(error);
return {};
}
}
sudo systemctl start redis-server
Create you own configuration file:
export default registerAs('mine', () => ({
name: process.env.MY_CONF_NAME,
pass: process.env.MY_CONF_PASS,
}));
Then include the configurations in the app.module.ts
import { appConfig, databaseConfig, mineConfig } from './configs';
ConfigModule.forRoot({
load: [databaseConfig, appConfig, mineConfig],
}),
- After starting your Nest.js application, open a web browser and navigate to the following URL:
http://localhost:3000/api
Replace
localhost:3000
with your actual server address and port. - Add you custom swagger options in the main.ts
const options: SwaggerCustomOptions = {
customCssUrl: '/swagger.css',
customSiteTitle: 'Ready to go swagger',
};
SwaggerModule.setup('api', app, document, options);
We extend our heartfelt gratitude to the following individuals, projects, and communities that have played a significant role in the development and success of Ready to Go Nest
Your support and contributions are deeply appreciated and have been instrumental in making Ready to Go Nest a powerful tool for Nest.js developers worldwide.