init
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
import { Injectable, NotFoundException, ForbiddenException, Logger, BadRequestException } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { Application } from './entities/application.entity';
|
||||
import { CreateApplicationDto, UpdateApplicationDto } from './dto/application.dto';
|
||||
import { ClustersService } from '../clusters/clusters.service';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationsService {
|
||||
private readonly logger = new Logger(ApplicationsService.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(Application)
|
||||
private appsRepository: Repository<Application>,
|
||||
private clustersService: ClustersService,
|
||||
private configService: ConfigService,
|
||||
) {}
|
||||
|
||||
async create(userId: string, dto: CreateApplicationDto): Promise<Application> {
|
||||
// Auto-assign default cluster if not specified
|
||||
let clusterId = dto.clusterId;
|
||||
if (!clusterId) {
|
||||
try {
|
||||
const defaultCluster = await this.clustersService.getDefault();
|
||||
clusterId = defaultCluster.id;
|
||||
this.logger.log(`Auto-assigned default cluster "${defaultCluster.name}" to app "${dto.name}"`);
|
||||
} catch {
|
||||
this.logger.warn('No default cluster found — app will be created without cluster assignment');
|
||||
}
|
||||
}
|
||||
|
||||
const app = this.appsRepository.create({
|
||||
...dto,
|
||||
userId,
|
||||
clusterId,
|
||||
subdomain: `${dto.name}-${userId.split('-')[0]}`,
|
||||
});
|
||||
return this.appsRepository.save(app);
|
||||
}
|
||||
|
||||
async findAllByUser(userId: string): Promise<Application[]> {
|
||||
return this.appsRepository.find({
|
||||
where: { userId },
|
||||
relations: ['deployments'],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(): Promise<Application[]> {
|
||||
return this.appsRepository.find({
|
||||
relations: ['user', 'deployments'],
|
||||
order: { createdAt: 'DESC' },
|
||||
});
|
||||
}
|
||||
|
||||
async findOne(id: string, userId?: string): Promise<Application> {
|
||||
const where: any = { id };
|
||||
if (userId) {
|
||||
where.userId = userId;
|
||||
}
|
||||
|
||||
const app = await this.appsRepository.findOne({
|
||||
where,
|
||||
relations: ['deployments'],
|
||||
});
|
||||
|
||||
if (!app) {
|
||||
throw new NotFoundException('Application not found');
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
async update(id: string, userId: string, dto: UpdateApplicationDto): Promise<Application> {
|
||||
const app = await this.findOne(id, userId);
|
||||
Object.assign(app, dto);
|
||||
return this.appsRepository.save(app);
|
||||
}
|
||||
|
||||
async delete(id: string, userId: string): Promise<Application> {
|
||||
const app = await this.findOne(id, userId);
|
||||
|
||||
// Delete uploaded files
|
||||
if (app.codePath) {
|
||||
try {
|
||||
const uploadDir = this.configService.get<string>('platform.uploadDir') || './uploads';
|
||||
const appDir = path.join(uploadDir, app.userId, app.id);
|
||||
if (fs.existsSync(appDir)) {
|
||||
fs.rmSync(appDir, { recursive: true, force: true });
|
||||
this.logger.log(`Deleted upload directory: ${appDir}`);
|
||||
}
|
||||
} catch (e: any) {
|
||||
this.logger.warn(`Failed to delete upload dir for ${app.name}: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
await this.appsRepository.remove(app);
|
||||
this.logger.log(`Deleted application ${app.name} (${id})`);
|
||||
return app;
|
||||
}
|
||||
|
||||
async updateImageTag(id: string, imageTag: string): Promise<Application> {
|
||||
const app = await this.findOne(id);
|
||||
app.latestImageTag = imageTag;
|
||||
return this.appsRepository.save(app);
|
||||
}
|
||||
|
||||
async uploadCode(id: string, userId: string, file: Express.Multer.File): Promise<Application> {
|
||||
if (!file) {
|
||||
throw new BadRequestException('No file uploaded');
|
||||
}
|
||||
|
||||
const app = await this.findOne(id, userId);
|
||||
const uploadDir = this.configService.get<string>('platform.uploadDir') || './uploads';
|
||||
const appDir = path.join(uploadDir, app.userId, app.id);
|
||||
|
||||
// Ensure directory exists
|
||||
fs.mkdirSync(appDir, { recursive: true });
|
||||
|
||||
// Save the zip file
|
||||
const zipPath = path.join(appDir, 'source.zip');
|
||||
fs.writeFileSync(zipPath, file.buffer);
|
||||
|
||||
// Update app with code path
|
||||
app.codePath = zipPath;
|
||||
const saved = await this.appsRepository.save(app);
|
||||
|
||||
this.logger.log(`Uploaded code for ${app.name} → ${zipPath} (${(file.size / 1024).toFixed(1)} KB)`);
|
||||
return saved;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user