Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,537 changes: 1,430 additions & 107 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 24 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,44 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
"test:e2e": "jest --config ./test/jest-e2e.json",
"seed": "ts-node src/api/seeders/user.seeder.ts"
},
"dependencies": {
"@casl/ability": "^6.7.3",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/jwt": "^11.0.0",
"@nestjs/passport": "^11.0.5",
"@nestjs/platform-express": "^10.4.17",
"@nestjs/typeorm": "^11.0.0",
"bcrypt": "^5.1.1",
"cache-manager": "^6.4.2",
"cache-manager-redis-store": "^3.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"multer": "^1.4.5-lts.2",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"pg": "^8.14.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"typeorm": "^0.3.22",
"uuid": "^11.1.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/bcrypt": "^5.0.2",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.2",
"@types/multer": "^1.4.12",
"@types/node": "^20.3.1",
"@types/passport-jwt": "^4.0.1",
"@types/supertest": "^2.0.12",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
Expand Down
36 changes: 36 additions & 0 deletions src/admin/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Controller, Get, Post, Put, Delete, Param, Body } from '@nestjs/common';
import { AdminService } from './admin.service';
import { Admin } from './entities/admin.entity';

@Controller('admins')
export class AdminController {
constructor(private readonly adminService: AdminService) {}

@Get()
async findAll(): Promise<Admin[]> {
return this.adminService.findAll();
}

@Get(':id')
async findOne(@Param('id') id: string): Promise<Admin> {
return this.adminService.findOne(id);
}

@Post()
async create(@Body() adminData: Partial<Admin>): Promise<Admin> {
return this.adminService.create(adminData);
}

@Put(':id')
async update(
@Param('id') id: string,
@Body() adminData: Partial<Admin>,
): Promise<Admin> {
return this.adminService.update(id, adminData);
}

@Delete(':id')
async delete(@Param('id') id: string): Promise<void> {
return this.adminService.delete(id);
}
}
13 changes: 13 additions & 0 deletions src/admin/admin.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AdminController } from './admin.controller';
import { AdminService } from './admin.service';
import { Admin } from './entities/admin.entity';

@Module({
imports: [TypeOrmModule.forFeature([Admin])],
controllers: [AdminController],
providers: [AdminService],
exports: [AdminService],
})
export class AdminModule {}
34 changes: 34 additions & 0 deletions src/admin/admin.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Admin } from './entities/admin.entity';

@Injectable()
export class AdminService {
constructor(
@InjectRepository(Admin)
private readonly adminRepository: Repository<Admin>,
) {}

async findAll(): Promise<Admin[]> {
return this.adminRepository.find();
}

async findOne(id: string): Promise<Admin> {
return this.adminRepository.findOneBy({ id });
}

async create(adminData: Partial<Admin>): Promise<Admin> {
const admin = this.adminRepository.create(adminData);
return this.adminRepository.save(admin);
}

async update(id: string, adminData: Partial<Admin>): Promise<Admin> {
await this.adminRepository.update(id, adminData);
return this.findOne(id);
}

async delete(id: string): Promise<void> {
await this.adminRepository.delete(id);
}
}
19 changes: 19 additions & 0 deletions src/admin/entities/admin.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm';

@Entity('admins')
export class Admin {
@PrimaryGeneratedColumn('uuid')
id: string;

@Column({ unique: true })
username: string;

@Column({ unique: true })
email: string;

@Column()
password: string;

@CreateDateColumn()
createdAt: Date;
}
6 changes: 4 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
import { AdminModule } from './admin/admin.module';

@Module({
imports: [],
imports: [DatabaseModule, AdminModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
export class AppModule {}
29 changes: 29 additions & 0 deletions src/database/database.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'postgres',
host: configService.get<string>('PG_HOST'),
port: configService.get<number>('PG_PORT'),
username: configService.get<string>('PG_USER'),
password: configService.get<string>('PG_PASS'),
database: configService.get<string>('PG_DATABASE'),
entities: ['dist/database/entities/**/*.entity{.ts,.js}'],
migrations: ['dist/database/migrations/*{.ts,.js}'],
synchronize: false,
logging: true,
ssl: {
rejectUnauthorized: false,
},
}),
}),
],
})
export class DatabaseModule {}
19 changes: 19 additions & 0 deletions src/database/entities/user.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm';

@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;

@Column({ unique: true })
username: string;

@Column()
email: string;

@Column()
password: string;

@CreateDateColumn()
createdAt: Date;
}
19 changes: 19 additions & 0 deletions src/database/migrations/1651234567890-CreateUsersTable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class CreateUsersTable1651234567890 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE users;`);
}
}
17 changes: 17 additions & 0 deletions src/database/seeders/user.seeder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { DataSource } from 'typeorm';
import { User } from '../entities/user.entity';
export async function seedUsers(dataSource: DataSource): Promise<void> {
const userRepository = dataSource.getRepository(User);

const users = [
{ username: 'dan_nura', email: 'nura@example.com', password: 'password123' },
{ username: 'ife_oluwa', email: 'ife@example.com', password: 'password456' },
];

for (const user of users) {
const existingUser = await userRepository.findOneBy({ email: user.email });
if (!existingUser) {
await userRepository.save(user);
}
}
}
8 changes: 7 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DataSource } from 'typeorm';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

// Run migrations
const dataSource = app.get(DataSource);
await dataSource.runMigrations();

await app.listen(3000);
}
bootstrap();
bootstrap();