Database & Auth
TypeORM Setup
// app.module.ts
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
type: 'postgres',
url: config.get('DATABASE_URL'),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
migrations: [__dirname + '/migrations/*{.ts,.js}'],
synchronize: config.get('NODE_ENV') !== 'production', // never in prod!
ssl: config.get('NODE_ENV') === 'production' ? { rejectUnauthorized: false } : false,
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
// Entity
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, ManyToOne, OneToMany } from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
email: string;
@Column()
name: string;
@Column({ select: false }) // excluded from SELECT by default
password: string;
@Column({ default: false })
isActive: boolean;
@OneToMany(() => Order, order => order.user)
orders: Order[];
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
// Feature module
@Module({
imports: [TypeOrmModule.forFeature([User, Order])],
controllers: [UsersController],
providers: [UsersService],
exports: [TypeOrmModule],
})
export class UsersModule {}JWT Authentication
// auth.module.ts
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
@Module({
imports: [
UsersModule,
PassportModule,
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
secret: config.get('JWT_SECRET'),
signOptions: { expiresIn: '15m' },
}),
inject: [ConfigService],
}),
],
providers: [AuthService, LocalStrategy, JwtStrategy],
controllers: [AuthController],
})
export class AuthModule {}
// auth.service.ts
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}
async validateUser(email: string, password: string): Promise<User | null> {
const user = await this.usersService.findByEmail(email);
if (user && await bcrypt.compare(password, user.password)) {
return user;
}
return null;
}
async login(user: User) {
const payload = { sub: user.id, email: user.email };
return {
access_token: this.jwtService.sign(payload),
refresh_token: this.jwtService.sign(payload, { expiresIn: '7d' }),
};
}
}
// auth.controller.ts
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@Post('login')
@UseGuards(LocalAuthGuard)
async login(@Request() req) {
return this.authService.login(req.user);
}
@Get('me')
@UseGuards(JwtAuthGuard)
getProfile(@CurrentUser() user) {
return user;
}
}Swagger / OpenAPI
// main.ts
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
const config = new DocumentBuilder()
.setTitle('My API')
.setDescription('API docs')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document); // available at /api
// DTO decorators
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class CreateUserDto {
@ApiProperty({ example: 'user@example.com' })
@IsEmail()
email: string;
@ApiPropertyOptional({ description: 'Optional bio' })
@IsOptional()
bio?: string;
}
// Controller decorators
@ApiTags('users')
@ApiBearerAuth()
@Controller('users')
export class UsersController {
@ApiOperation({ summary: 'Get all users' })
@ApiResponse({ status: 200, type: [User] })
@Get()
findAll() { ... }
}Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free