mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-21 22:46:41 +02:00
166 lines
4.2 KiB
TypeScript
166 lines
4.2 KiB
TypeScript
import { Injectable, Inject, NotFoundException, BadRequestException } from '@nestjs/common';
|
|
import { eq, and, isNull } from 'drizzle-orm';
|
|
import { DATABASE_CONNECTION } from '../db/database.module';
|
|
import { Database } from '../db/connection';
|
|
import { files, fileVersions } from '../db/schema';
|
|
import type { File, NewFile, NewFileVersion } from '../db/schema';
|
|
import { StorageService } from '../storage/storage.service';
|
|
import { CreateFileDto, UpdateFileDto, MoveFileDto } from './dto/create-file.dto';
|
|
|
|
@Injectable()
|
|
export class FileService {
|
|
constructor(
|
|
@Inject(DATABASE_CONNECTION) private db: Database,
|
|
private storageService: StorageService
|
|
) {}
|
|
|
|
async findAll(userId: string, parentFolderId?: string): Promise<File[]> {
|
|
if (parentFolderId) {
|
|
return this.db
|
|
.select()
|
|
.from(files)
|
|
.where(
|
|
and(
|
|
eq(files.userId, userId),
|
|
eq(files.parentFolderId, parentFolderId),
|
|
eq(files.isDeleted, false)
|
|
)
|
|
);
|
|
}
|
|
|
|
// Root files (no parent folder)
|
|
return this.db
|
|
.select()
|
|
.from(files)
|
|
.where(
|
|
and(eq(files.userId, userId), isNull(files.parentFolderId), eq(files.isDeleted, false))
|
|
);
|
|
}
|
|
|
|
async findOne(userId: string, id: string): Promise<File> {
|
|
const result = await this.db
|
|
.select()
|
|
.from(files)
|
|
.where(and(eq(files.id, id), eq(files.userId, userId), eq(files.isDeleted, false)));
|
|
|
|
if (result.length === 0) {
|
|
throw new NotFoundException('File not found');
|
|
}
|
|
|
|
return result[0];
|
|
}
|
|
|
|
async upload(userId: string, file: Express.Multer.File, dto: CreateFileDto): Promise<File> {
|
|
if (!file) {
|
|
throw new BadRequestException('No file provided');
|
|
}
|
|
|
|
// Upload to S3
|
|
const uploadResult = await this.storageService.uploadFile(
|
|
userId,
|
|
file.buffer,
|
|
file.originalname,
|
|
file.mimetype
|
|
);
|
|
|
|
// Create file record
|
|
const newFile: NewFile = {
|
|
userId,
|
|
name: file.originalname,
|
|
originalName: file.originalname,
|
|
mimeType: file.mimetype,
|
|
size: file.size,
|
|
storagePath: uploadResult.storagePath,
|
|
storageKey: uploadResult.storageKey,
|
|
parentFolderId: dto.parentFolderId || null,
|
|
currentVersion: 1,
|
|
};
|
|
|
|
const result = await this.db.insert(files).values(newFile).returning();
|
|
const createdFile = result[0];
|
|
|
|
// Create initial version record
|
|
const version: NewFileVersion = {
|
|
fileId: createdFile.id,
|
|
versionNumber: 1,
|
|
storagePath: uploadResult.storagePath,
|
|
storageKey: uploadResult.storageKey,
|
|
size: file.size,
|
|
createdBy: userId,
|
|
};
|
|
|
|
await this.db.insert(fileVersions).values(version);
|
|
|
|
return createdFile;
|
|
}
|
|
|
|
async update(userId: string, id: string, dto: UpdateFileDto): Promise<File> {
|
|
await this.findOne(userId, id);
|
|
|
|
const result = await this.db
|
|
.update(files)
|
|
.set({
|
|
...dto,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(and(eq(files.id, id), eq(files.userId, userId)))
|
|
.returning();
|
|
|
|
return result[0];
|
|
}
|
|
|
|
async move(userId: string, id: string, dto: MoveFileDto): Promise<File> {
|
|
await this.findOne(userId, id);
|
|
|
|
const result = await this.db
|
|
.update(files)
|
|
.set({
|
|
parentFolderId: dto.parentFolderId || null,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(and(eq(files.id, id), eq(files.userId, userId)))
|
|
.returning();
|
|
|
|
return result[0];
|
|
}
|
|
|
|
async delete(userId: string, id: string): Promise<void> {
|
|
await this.findOne(userId, id);
|
|
|
|
// Soft delete
|
|
await this.db
|
|
.update(files)
|
|
.set({
|
|
isDeleted: true,
|
|
deletedAt: new Date(),
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(and(eq(files.id, id), eq(files.userId, userId)));
|
|
}
|
|
|
|
async toggleFavorite(userId: string, id: string): Promise<File> {
|
|
const file = await this.findOne(userId, id);
|
|
|
|
const result = await this.db
|
|
.update(files)
|
|
.set({
|
|
isFavorite: !file.isFavorite,
|
|
updatedAt: new Date(),
|
|
})
|
|
.where(and(eq(files.id, id), eq(files.userId, userId)))
|
|
.returning();
|
|
|
|
return result[0];
|
|
}
|
|
|
|
async download(userId: string, id: string): Promise<{ buffer: Buffer; file: File }> {
|
|
const file = await this.findOne(userId, id);
|
|
const buffer = await this.storageService.downloadFile(file.storageKey);
|
|
return { buffer, file };
|
|
}
|
|
|
|
async getDownloadUrl(userId: string, id: string): Promise<string> {
|
|
const file = await this.findOne(userId, id);
|
|
return this.storageService.getDownloadUrl(file.storageKey);
|
|
}
|
|
}
|