Introduction
The primary goal of this project is to illustrate the process of connecting a Neon database to a NestJS application through the Config Service, which helps manage configuration settings in a clean and organized manner. Neon PostgreSQL is designed to deliver a seamless database experience without the hassle of managing infrastructure.
In addition, I will demonstrate (in another guide) how to implement create and manage database entities with TypeORM, a popular Object-Relational Mapping (ORM) tool, to define and manage database entities.
Prerequisites
A NestJS and TypeScript project already initialized -> If you don't have a NestJS project set up yet, you can follow the official NestJS guide to initialize a new project with TypeScript. (Link)
An account on Neon PostgreSQL -> You can sign up for a Neon PostgreSQL account (Link)
For setting up a new project in Neon PostgreSQL, you can follow their official guide (official link). As of now, Neon PostgreSQL offers advantageous free solutions when setting up a new project
Packages
In addition to the packages provided by Nest on the initial setup, the following dependencies will help us to connect to Neon database.
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^3.2.2",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.3.10",
"@nestjs/typeorm": "^10.0.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"pg": "^8.12.0",
"typeorm": "^0.3.20",
}
Configuring Environment Variables
Create a .env file in the root directory of your NestJS project. This file will contain all the necessary environment variables for your application. Below there is an example of a ".env" file for our project
# ====== NEON POSTGRES ====== #
DATABASE_HOST='NEON PGHOST'
DATABASE_USER='NEON PGUSER'
DATABASE_PASSWORD='NEON PGPASSWORD'
DATABASE_PORT= 5432 #(usually it's 5432)
DATABASE_ENDPOINT_ID='NEON ENDPOINT_ID'
DATABASE_NAME='NEON PGDATABASE'
# ====== PORTS ====== #
NEST_PORT= YOUR_NEST_PORT #(usually it's 3000)
Given that the prerequisite N°3 has been met and you have successfully created a project on Neon PostgreSQL, you will find the necessary environment variables directly from the Neon dashboard. Here is an image illustrating the relevant variables you will need to configure
(1) Configuring the Nest.JS Project -> config/ folder
We'll start by organizing our configuration files in the config folder. Here, we'll create two essential files: app.config.ts
and database.config.ts
app.config.ts
This setup register the application configuration settings under the name 'config' with @nestjs/config. Here we will define the port and node environment.
import { registerAs } from '@nestjs/config';
export default registerAs('config', () => ({
port: parseInt(process.env.NEST_PORT, 10) || 5575,
nodenv: process.env.NODE_ENV,
}));
database.config.ts
This setup configures the connection options for Neon PostgreSQL database connections using the environment variables defined earlier. It utilizes @nestjs/config
to manage environment variables
import { registerAs } from '@nestjs/config';
export default registerAs('database', () => ({
type: 'postgres', // Neon PostgreSQL database type
host: process.env.DATABASE_HOST || 'localhost',
database: process.env.DATABASE_NAME,
port: process.env.DATABASE_PORT,
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
entities: [`${__dirname}/../**/*.entity{.ts,.js}`], // TypeORM Entities to be stored in the database
subscribers: [`${__dirname}/../**/*.subscriber{.ts,.js}`], // OPTIONAL
synchronize: process.env.NODE_ENV === 'development', // Set `true` to synchronize the database schema with the entities
logging: process.env.NODE_ENV === 'development',
ssl: true,
connection: {
options: `project=${process.env.DATABASE_ENDPOINT_ID}`,
},
migrations: [`${__dirname}/../database/migrations/*{.ts,.js}`], // Migrations
migrationsTableName: 'typeorm-migrations', // Set the name of the migrations table
}))
index.ts
This index.ts file simplifies exporting configurations by re-exporting AppConfig
and DatabaseConfig
from their respective files
export { default as AppConfig } from './app.config';
export { default as DatabaseConfig } from './database.config';
(2) Configuring the Nest.JS Project -> database/ folder
Inside this folder we configure a TypeORM DataSource for Neon database using settings from environment variables.
typeorm.config.ts
// ====== IMPORTS =========
import { DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';
config();
// 1. Define a configuration for TypeORM
const configService = new ConfigService();
export default new DataSource({
type: 'postgres', // Neon PostgreSQL database type
host: configService.get<string>('DATABASE_HOST'),
database: configService.get<string>('DATABASE_NAME'),
port: configService.get<number>('DATABASE_PORT'),
username: configService.get<string>('DATABASE_USER'),
password: configService.get<string>('DATABASE_PASSWORD'),
entities: [`${__dirname}/../src/**/*.entity{.ts,.js}`],
subscribers: [`${__dirname}/../**/*.subscriber{.ts,.js}`] // OPTIONAL,
synchronize: process.env.NODE_ENV === 'development',
logging: process.env.NODE_ENV === 'development',
ssl: true,
migrations: [`${__dirname}/../database/migrations/*{.ts,.js}`],
migrationsTableName: 'typeorm-migrations', // Set the same name as you did on database.config
})
From now on, this file will manage the entities you create in your project. Additionally, if you need to make modifications to the database schema, the setup includes support for using migrations.
(3) Configuring the Nest.JS Project -> app.module.ts
The app.module.ts
orchestrates the main structure and dependencies of the NestJS application. It imports the necessary modules to configures TypeORM for database access using environment variables.
// ======== MODULES =========
import { Module, forwardRef } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
// ======== CONTROLLERS =========
import { AppController } from './app.controller';
// ======== SERVICES =========
import { AppService } from './app.service';
// ======== CONFIG =========
import { AppConfig, DatabaseConfig } from 'config/index';
@Module({
imports: [
// Load environment variables
ConfigModule.forRoot({
isGlobal: true, // Set `true` for global configuration
cache: true,
load: [AppConfig, DatabaseConfig],
}),
// TypeORM configuration
TypeOrmModule.forRootAsync({
imports: [ConfigModule], // Import the ConfigModule
useFactory: (configService: ConfigService) => ({
...configService.get('database'),
}),
inject: [ConfigService], // Inject the ConfigService
}),
// Other Project Modules
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }
(4) Configuring the Nest.JS Project -> main.ts
This main.ts
file initializes the NestJS application, sets up middleware, establishes a database connection using configuration from ConfigService, and starts the server to handle incoming requests.
// ====== IMPORTS ======
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as dotenv from 'dotenv';
import { static as expose } from 'express';
import { ConfigService } from '@nestjs/config';
dotenv.config();
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Configuration Service
const configService = app.get(ConfigService);
const port = configService.get('NEST_PORT');
await app
.listen(port || 3375)
.then(() => {
console.log('Current Database Name: ', configService.get('DATABASE_NAME'));
console.log(`Application is running on port`, configService.get('NEST_PORT'));
})
.catch((err) => {
console.error('Error while starting application: ', err.message);
});
}
bootstrap();
Conclusion
The configuration steps are now complete. To start the application and connect to the configured database, simply run the following command:
yarn start:dev OR yarn start
You should see the database connection details in the terminal, indicating that the connection has been successfully established like the picture below
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more