Skip to content
Draft
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
5 changes: 5 additions & 0 deletions apps/api/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Application Configuration
PORT=8000

# Redis Configuration
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=your_strong_password_here

# Supabase Configuration
SUPABASE_URL=your_supabase_url
SUPABASE_SERVICE_KEY=your_supabase_service_key_here
11 changes: 10 additions & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dev": "nest start --watch",
"build": "nest build",
"start": "nest start",
"start:worker": "cross-env NODE_ENV=worker nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"test": "jest",
Expand All @@ -16,19 +17,27 @@
"type-check": "tsc --noEmit"
},
"dependencies": {
"@elevenlabs/elevenlabs-js": "^2.21.0",
"@nestjs/bullmq": "^10.2.1",
"@nestjs/common": "^10.0.0",
"@nestjs/config": "^4.0.2",
"@nestjs/core": "^10.0.0",
"@nestjs/jwt": "^11.0.1",
"@nestjs/platform-express": "^10.0.0",
"@repo/api": "workspace:*",
"@repo/queues": "workspace:*",
"@repo/supabase": "workspace:*",
"@repo/validation": "workspace:*",
"@supabase/supabase-js": "^2.53.0",
"@tabler/icons-react": "^3.34.1",
"bullmq": "^5.62.2",
"clsx": "^2.1.1",
"jsonrepair": "^3.13.0",
"motion": "^12.23.12",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"tailwind-merge": "^2.6.0"
"tailwind-merge": "^2.6.0",
"ytdl-core": "^4.11.5"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
Expand Down
18 changes: 14 additions & 4 deletions apps/api/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { Controller, Get } from '@nestjs/common';
import { Controller, Get, Req, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { SupabaseService } from './supabase/supabase.service';
import { SupabaseAuthGuard } from './guards/auth.guard';

@Controller()
@UseGuards(SupabaseAuthGuard)
export class AppController {
constructor(private readonly appService: AppService) {}
constructor(private readonly appService: AppService, private readonly supabaseService: SupabaseService) { }

@Get()
getHello(): string {
return this.appService.getHello();
getTrainAI() {
return { message: 'Protected train-ai endpoint' };
}

@Get('test-db')
async testDb(@Req() req) {
const { data, error } = await this.supabaseService.getClient().from('profiles').select('*').limit(1);
if (error) throw error;
return data;
}
}
35 changes: 28 additions & 7 deletions apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,42 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';

import { LinksModule } from './links/links.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { BullModule } from '@nestjs/bullmq';
import { TrainAiProcessor } from '@repo/queues';
import redisConfig from './config/redis.config';
import { SupabaseModule } from './supabase/supabase.module';

import { AppService } from './app.service';
import { AppController } from './app.controller';
import { TrainAiController } from './train-ai/train-ai.controller';
import { TrainAiModule } from './train-ai/train-ai.module';

@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
load: [redisConfig]
}),
BullModule.forRootAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
connection: configService.get('redis'),
defaultJobOptions: {
attempts: 3,
backoff: { type: 'exponential', delay: 1000 },
removeOnComplete: { count: 1000 },
removeOnFail: { count: 5000 },
limiter: { max: 100, duration: 60000 }
},
}),
inject: [ConfigService],
}),
BullModule.registerQueue({
name: 'train-ai'
}),
SupabaseModule,
LinksModule,
TrainAiModule
],
controllers: [AppController],
providers: [AppService],
controllers: [AppController, TrainAiController],
providers: [AppService, TrainAiProcessor],
})
export class AppModule {}
export class AppModule { }
7 changes: 7 additions & 0 deletions apps/api/src/config/redis.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { registerAs } from '@nestjs/config';

export default registerAs('redis', () => ({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_PASSWORD,
}));
14 changes: 0 additions & 14 deletions apps/api/src/config/supabase.config.ts

This file was deleted.

25 changes: 25 additions & 0 deletions apps/api/src/guards/auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { SupabaseService } from '../supabase/supabase.service';

@Injectable()
export class SupabaseAuthGuard implements CanActivate {
constructor(private supabaseService: SupabaseService) { }

async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.split(' ')[1]; // Bearer <token>

if (!token) {
throw new UnauthorizedException('No token provided');
}

// Validate Supabase JWT
const { data, error } = await this.supabaseService.getClient().auth.getUser(token);
if (error || !data.user) {
throw new UnauthorizedException('Invalid or expired token');
}

request.user = data.user;
return true;
}
}
22 changes: 0 additions & 22 deletions apps/api/src/links/links.controller.spec.ts

This file was deleted.

43 changes: 0 additions & 43 deletions apps/api/src/links/links.controller.ts

This file was deleted.

10 changes: 0 additions & 10 deletions apps/api/src/links/links.module.ts

This file was deleted.

19 changes: 0 additions & 19 deletions apps/api/src/links/links.service.spec.ts

This file was deleted.

59 changes: 0 additions & 59 deletions apps/api/src/links/links.service.ts

This file was deleted.

36 changes: 34 additions & 2 deletions apps/api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,38 @@ import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(process.env.PORT || 8080);

// Check if this instance should run as a worker
const isWorker = process.env.NODE_ENV === 'worker';

if (isWorker) {
// Initialize worker mode
await app.init();
console.log('Worker initialized successfully');
} else {
// Initialize API server mode
app.setGlobalPrefix('api/v1');

const allowedOrigins = [
process.env.FRONTEND_DEV_URL, // Local frontend
process.env.FRONTEND_PROD_URL, // Production frontend
"*" // Allow all origins (for testing purposes)
];

app.enableCors({
origin: (origin, callback) => {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
});

await app.listen(process.env.PORT || 8080, () => {
console.log(`API Server running on port ${process.env.PORT || 8080}`);
});
}
}
bootstrap();
bootstrap();
7 changes: 4 additions & 3 deletions apps/api/src/supabase/supabase.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Global, Module } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { SupabaseService } from './supabase.service';

@Global()
@Module({
imports: [ConfigModule],
providers: [SupabaseService],
exports: [SupabaseService],
})
export class SupabaseModule {}
export class SupabaseModule { }
Loading
Loading