feat: als and prisma
This commit is contained in:
@@ -1,10 +1,28 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { UserModule } from './user/user.module';
|
||||
import { AuthModule } from './auth/auth.module';
|
||||
import { RequestContextMiddleware } from 'core/als/request-context.middleware';
|
||||
import { RequestContextModule } from 'core/als/request-context.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { PrismaModule } from './prisma/prisma.module';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
}),
|
||||
UserModule,
|
||||
AuthModule,
|
||||
RequestContextModule,
|
||||
PrismaModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(RequestContextMiddleware).forRoutes('*paths');
|
||||
}
|
||||
}
|
||||
|
||||
18
src/auth/auth.controller.spec.ts
Normal file
18
src/auth/auth.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthController } from './auth.controller';
|
||||
|
||||
describe('AuthController', () => {
|
||||
let controller: AuthController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AuthController],
|
||||
}).compile();
|
||||
|
||||
controller = module.get<AuthController>(AuthController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
4
src/auth/auth.controller.ts
Normal file
4
src/auth/auth.controller.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Controller } from '@nestjs/common';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {}
|
||||
9
src/auth/auth.module.ts
Normal file
9
src/auth/auth.module.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthController } from './auth.controller';
|
||||
|
||||
@Module({
|
||||
providers: [AuthService],
|
||||
controllers: [AuthController]
|
||||
})
|
||||
export class AuthModule {}
|
||||
18
src/auth/auth.service.spec.ts
Normal file
18
src/auth/auth.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [AuthService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<AuthService>(AuthService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
4
src/auth/auth.service.ts
Normal file
4
src/auth/auth.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {}
|
||||
1
src/auth/types/index.ts
Normal file
1
src/auth/types/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './jwt';
|
||||
26
src/auth/types/jwt.ts
Normal file
26
src/auth/types/jwt.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export interface UserPayload {
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
userId: string;
|
||||
email: string;
|
||||
role: 'user';
|
||||
}
|
||||
|
||||
// For restaurant owners, also resId
|
||||
export interface StaffPayload {
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
userId: string;
|
||||
email: string;
|
||||
role: 'staff';
|
||||
}
|
||||
|
||||
export interface AdminPayload {
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
userId: string;
|
||||
email: string;
|
||||
role: 'admin';
|
||||
}
|
||||
|
||||
export type AuthPayload = UserPayload | StaffPayload | AdminPayload;
|
||||
@@ -1,8 +1,13 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
|
||||
const config = app.get(ConfigService);
|
||||
const port = config.get<number>('PORT') ?? 3000;
|
||||
|
||||
await app.listen(port);
|
||||
}
|
||||
bootstrap();
|
||||
|
||||
10
src/prisma/prisma.module.ts
Normal file
10
src/prisma/prisma.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { PrismaService } from './prisma.service';
|
||||
import { RequestContextModule } from 'core/als/request-context.module';
|
||||
|
||||
@Module({
|
||||
imports: [RequestContextModule],
|
||||
providers: [PrismaService],
|
||||
exports: [PrismaService],
|
||||
})
|
||||
export class PrismaModule {}
|
||||
57
src/prisma/prisma.service.ts
Normal file
57
src/prisma/prisma.service.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
Global,
|
||||
Injectable,
|
||||
OnModuleDestroy,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common';
|
||||
import { PrismaClient } from 'prisma/generated/prisma/client';
|
||||
import { Pool } from 'pg';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
import { RequestContextService } from 'core/als/request-context.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Global()
|
||||
@Injectable()
|
||||
export class PrismaService
|
||||
extends PrismaClient
|
||||
implements OnModuleDestroy, OnModuleInit
|
||||
{
|
||||
constructor(
|
||||
private readonly ctx: RequestContextService,
|
||||
private readonly configService: ConfigService,
|
||||
) {
|
||||
const connectionString = configService.get<string>('DATABASE_URL');
|
||||
const connectionPool = new Pool({
|
||||
connectionString,
|
||||
});
|
||||
console.log(connectionString);
|
||||
|
||||
const adapter = new PrismaPg(connectionPool);
|
||||
|
||||
super({
|
||||
adapter: adapter,
|
||||
log: ['info', 'error', 'warn'],
|
||||
});
|
||||
}
|
||||
async onModuleInit() {
|
||||
try {
|
||||
await this.$connect();
|
||||
await this.$queryRaw`SELECT 1`;
|
||||
} catch (err) {
|
||||
console.error('❌ Prisma connection failed');
|
||||
// throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async onModuleDestroy() {
|
||||
await this.$disconnect();
|
||||
}
|
||||
|
||||
/*
|
||||
* For shared transaction across services. If present, return the transaction.
|
||||
* Else returns itself.
|
||||
* */
|
||||
get client() {
|
||||
return this.ctx.get().tx ?? this;
|
||||
}
|
||||
}
|
||||
7
src/user/user.module.ts
Normal file
7
src/user/user.module.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
@Module({
|
||||
providers: [UserService]
|
||||
})
|
||||
export class UserModule {}
|
||||
18
src/user/user.service.spec.ts
Normal file
18
src/user/user.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { UserService } from './user.service';
|
||||
|
||||
describe('UserService', () => {
|
||||
let service: UserService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [UserService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<UserService>(UserService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
4
src/user/user.service.ts
Normal file
4
src/user/user.service.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class UserService {}
|
||||
Reference in New Issue
Block a user