init db with migration, create users table

This commit is contained in:
Paul Coral
2025-07-28 08:16:34 +02:00
parent 8b327dcb18
commit c3881d7ff7
24 changed files with 494 additions and 23 deletions

View File

@@ -5,7 +5,7 @@ import { AppService } from './app.service';
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
@Get('hello')
getHello(): string {
return this.appService.getHello();
}

View File

@@ -1,11 +1,11 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HelloController } from './hello/hello.controller';
import { AuthController } from './controllers/auth/auth.controller';
@Module({
imports: [],
controllers: [AppController, HelloController],
controllers: [AppController, AuthController],
providers: [AppService],
})
export class AppModule {}

View File

@@ -1,15 +1,15 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HelloController } from './hello.controller';
import { AuthController } from './auth.controller';
describe('HelloController', () => {
let controller: HelloController;
describe('AuthController', () => {
let controller: AuthController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HelloController],
controllers: [AuthController],
}).compile();
controller = module.get<HelloController>(HelloController);
controller = module.get<AuthController>(AuthController);
});
it('should be defined', () => {

View File

@@ -0,0 +1,12 @@
import { AuthApiService } from '@my-monorepo/common';
import { Controller, Post } from '@nestjs/common';
@Controller(AuthApiService.baseUrl)
export class AuthController implements AuthApiService {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
@Post(AuthApiService.postCredentials)
// eslint-disable-next-line @typescript-eslint/require-await
async postCredentials() {
return 'hello';
}
}

View File

@@ -0,0 +1,22 @@
import { Pool } from 'pg';
import { Kysely, PostgresDialect } from 'kysely';
const dialect = new PostgresDialect({
// TODO : temporary data, make to .env
pool: new Pool({
database: 'cowsi',
host: 'localhost',
user: 'postgres',
password: 'postgres',
port: 5432,
max: 10,
}),
});
// Database interface is passed to Kysely's constructor, and from now on, Kysely
// knows your database structure.
// Dialect is passed to Kysely's constructor, and from now on, Kysely knows how
// to communicate with your database.
export const db = new Kysely<any>({
dialect,
});

View File

@@ -1,4 +0,0 @@
import { Controller } from '@nestjs/common';
@Controller()
export class HelloController {}

View File

@@ -0,0 +1,56 @@
import * as path from 'path';
import { Pool } from 'pg';
import { promises as fs } from 'fs';
import {
Kysely,
Migrator,
PostgresDialect,
FileMigrationProvider,
} from 'kysely';
import { ZodUnknownDef } from 'zod';
async function migrateToLatest() {
const db = new Kysely<ZodUnknownDef>({
dialect: new PostgresDialect({
pool: new Pool({
database: 'cowsi',
host: 'localhost',
user: 'postgres',
password: 'postgres',
port: 5432,
}),
}),
});
const migrator = new Migrator({
db,
provider: new FileMigrationProvider({
fs,
path,
// This needs to be an absolute path.
migrationFolder: path.join(__dirname, './migrations'),
}),
});
const { error, results } = await migrator.migrateToLatest();
results?.forEach((it) => {
if (it.status === 'Success') {
console.log(`migration "${it.migrationName}" was executed successfully`);
} else if (it.status === 'Error') {
console.error(`failed to execute migration "${it.migrationName}"`);
}
});
if (error) {
console.error('failed to migrate');
console.error(error);
process.exit(1);
} else {
console.log('Done migrating');
}
await db.destroy();
}
void migrateToLatest();

View File

@@ -0,0 +1,30 @@
import { Kysely, sql } from 'kysely';
export async function up(db: Kysely<unknown>): Promise<void> {
await db.schema
.createTable('users')
.addColumn('id', 'bigserial', (col) => col.primaryKey())
.addColumn('first_name', 'varchar(255)', (col) => col.notNull())
.addColumn('last_name', 'varchar(255)', (col) => col.notNull())
.addColumn('email', 'varchar(255)', (col) => col.notNull().unique())
.addColumn('hash', 'text')
.addColumn('created_at', 'timestamptz', (col) =>
col.notNull().defaultTo(sql`now()`),
)
.addColumn('updated_at', 'timestamptz', (col) =>
col.notNull().defaultTo(sql`now()`),
)
.addColumn('deleted_at', 'timestamptz')
.execute();
// You can also add indexes, foreign keys, etc. here
await db.schema
.createIndex('users_email_index')
.on('users')
.column('email')
.execute();
}
export async function down(db: Kysely<unknown>): Promise<void> {
await db.schema.dropTable('users').execute();
}