Refactoring

* replace TypeORM with Kysely query builder
* refactor migrations
* other changes and fixes
This commit is contained in:
Philipinho
2024-03-29 01:46:11 +00:00
parent cacb5606b1
commit c18c9ae02b
122 changed files with 2619 additions and 3541 deletions

View File

@ -14,10 +14,9 @@ import { FastifyReply, FastifyRequest } from 'fastify';
import { AttachmentInterceptor } from './attachment.interceptor';
import * as bytes from 'bytes';
import { AuthUser } from '../../decorators/auth-user.decorator';
import { User } from '../user/entities/user.entity';
import { AuthWorkspace } from '../../decorators/auth-workspace.decorator';
import { Workspace } from '../workspace/entities/workspace.entity';
import { JwtAuthGuard } from '../../guards/jwt-auth.guard';
import { User, Workspace } from '@docmost/db/types/entity.types';
@Controller('attachments')
export class AttachmentController {
@ -31,6 +30,7 @@ export class AttachmentController {
@Req() req: FastifyRequest,
@Res() res: FastifyReply,
@AuthUser() user: User,
@AuthWorkspace() workspace: Workspace,
) {
const maxFileSize = bytes('5MB');
@ -42,6 +42,7 @@ export class AttachmentController {
const fileResponse = await this.attachmentService.uploadAvatar(
file,
user.id,
workspace.id,
);
return res.send(fileResponse);

View File

@ -2,20 +2,12 @@ import { Module } from '@nestjs/common';
import { AttachmentService } from './attachment.service';
import { AttachmentController } from './attachment.controller';
import { StorageModule } from '../../integrations/storage/storage.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Attachment } from './entities/attachment.entity';
import { AttachmentRepository } from './repositories/attachment.repository';
import { UserModule } from '../user/user.module';
import { WorkspaceModule } from '../workspace/workspace.module';
@Module({
imports: [
TypeOrmModule.forFeature([Attachment]),
StorageModule,
UserModule,
WorkspaceModule,
],
imports: [StorageModule, UserModule, WorkspaceModule],
controllers: [AttachmentController],
providers: [AttachmentService, AttachmentRepository],
providers: [AttachmentService],
})
export class AttachmentModule {}

View File

@ -1,8 +1,6 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { StorageService } from '../../integrations/storage/storage.service';
import { MultipartFile } from '@fastify/multipart';
import { AttachmentRepository } from './repositories/attachment.repository';
import { Attachment } from './entities/attachment.entity';
import { UserService } from '../user/user.service';
import { UpdateUserDto } from '../user/dto/update-user.dto';
import {
@ -15,14 +13,16 @@ import {
import { v4 as uuid4 } from 'uuid';
import { WorkspaceService } from '../workspace/services/workspace.service';
import { UpdateWorkspaceDto } from '../workspace/dto/update-workspace.dto';
import { AttachmentRepo } from '@docmost/db/repos/attachment/attachment.repo';
// TODO: make code better
@Injectable()
export class AttachmentService {
constructor(
private readonly storageService: StorageService,
private readonly attachmentRepo: AttachmentRepository,
private readonly workspaceService: WorkspaceService,
private readonly userService: UserService,
private readonly attachmentRepo: AttachmentRepo,
) {}
async uploadToDrive(preparedFile: PreparedFile, filePath: string) {
@ -34,10 +34,10 @@ export class AttachmentService {
}
}
async updateUserAvatar(userId: string, avatarUrl: string) {
async updateUserAvatar(avatarUrl: string, userId: string, workspaceId) {
const updateUserDto = new UpdateUserDto();
updateUserDto.avatarUrl = avatarUrl;
await this.userService.update(userId, updateUserDto);
await this.userService.update(updateUserDto, userId, workspaceId);
}
async updateWorkspaceLogo(workspaceId: string, logoUrl: string) {
@ -46,7 +46,11 @@ export class AttachmentService {
await this.workspaceService.update(workspaceId, updateWorkspaceDto);
}
async uploadAvatar(filePromise: Promise<MultipartFile>, userId: string) {
async uploadAvatar(
filePromise: Promise<MultipartFile>,
userId: string,
workspaceId: string,
) {
try {
const preparedFile: PreparedFile = await prepareFile(filePromise);
const allowedImageTypes = ['.jpg', '.jpeg', '.png'];
@ -60,19 +64,19 @@ export class AttachmentService {
await this.uploadToDrive(preparedFile, filePath);
const attachment = new Attachment();
// todo: in transaction
const attachment = await this.attachmentRepo.insertAttachment({
creatorId: userId,
type: AttachmentType.Avatar,
filePath: filePath,
fileName: preparedFile.fileName,
fileSize: preparedFile.fileSize,
mimeType: preparedFile.mimeType,
fileExt: preparedFile.fileExtension,
workspaceId: workspaceId,
});
attachment.creatorId = userId;
attachment.pageId = null;
attachment.workspaceId = null;
attachment.type = AttachmentType.Avatar;
attachment.filePath = filePath;
attachment.fileName = preparedFile.fileName;
attachment.fileSize = preparedFile.fileSize;
attachment.mimeType = preparedFile.mimeType;
attachment.fileExt = preparedFile.fileExtension;
await this.updateUserAvatar(userId, filePath);
await this.updateUserAvatar(filePath, userId, workspaceId);
return attachment;
} catch (err) {
@ -102,17 +106,17 @@ export class AttachmentService {
await this.uploadToDrive(preparedFile, filePath);
const attachment = new Attachment();
attachment.creatorId = userId;
attachment.pageId = null;
attachment.workspaceId = workspaceId;
attachment.type = AttachmentType.WorkspaceLogo;
attachment.filePath = filePath;
attachment.fileName = preparedFile.fileName;
attachment.fileSize = preparedFile.fileSize;
attachment.mimeType = preparedFile.mimeType;
attachment.fileExt = preparedFile.fileExtension;
// todo: in trx
const attachment = await this.attachmentRepo.insertAttachment({
creatorId: userId,
type: AttachmentType.WorkspaceLogo,
filePath: filePath,
fileName: preparedFile.fileName,
fileSize: preparedFile.fileSize,
mimeType: preparedFile.mimeType,
fileExt: preparedFile.fileExtension,
workspaceId: workspaceId,
});
await this.updateWorkspaceLogo(workspaceId, filePath);
@ -143,17 +147,17 @@ export class AttachmentService {
await this.uploadToDrive(preparedFile, filePath);
const attachment = new Attachment();
attachment.creatorId = userId;
attachment.pageId = pageId;
attachment.workspaceId = workspaceId;
attachment.type = AttachmentType.WorkspaceLogo;
attachment.filePath = filePath;
attachment.fileName = preparedFile.fileName;
attachment.fileSize = preparedFile.fileSize;
attachment.mimeType = preparedFile.mimeType;
attachment.fileExt = preparedFile.fileExtension;
const attachment = await this.attachmentRepo.insertAttachment({
creatorId: userId,
pageId: pageId,
type: AttachmentType.File,
filePath: filePath,
fileName: preparedFile.fileName,
fileSize: preparedFile.fileSize,
mimeType: preparedFile.mimeType,
fileExt: preparedFile.fileExtension,
workspaceId: workspaceId,
});
return attachment;
} catch (err) {

View File

@ -1,65 +0,0 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
JoinColumn,
CreateDateColumn,
DeleteDateColumn,
} from 'typeorm';
import { User } from '../../user/entities/user.entity';
import { Page } from '../../page/entities/page.entity';
import { Workspace } from '../../workspace/entities/workspace.entity';
@Entity('attachments')
export class Attachment {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ type: 'varchar', length: 255 })
fileName: string;
@Column({ type: 'varchar' })
filePath: string;
@Column({ type: 'bigint' })
fileSize: number;
@Column({ type: 'varchar', length: 55 })
fileExt: string;
@Column({ type: 'varchar', length: 255 })
mimeType: string;
@Column({ type: 'varchar', length: 55 })
type: string; // e.g. page / workspace / avatar
@Column()
creatorId: string;
@ManyToOne(() => User)
@JoinColumn({ name: 'creatorId' })
creator: User;
@Column({ nullable: true })
pageId: string;
@ManyToOne(() => Page)
@JoinColumn({ name: 'pageId' })
page: Page;
@Column({ nullable: true })
workspaceId: string;
@ManyToOne(() => Workspace, {
onDelete: 'CASCADE',
})
@JoinColumn({ name: 'workspaceId' })
workspace: Workspace;
@CreateDateColumn()
createdAt: Date;
@DeleteDateColumn({ nullable: true })
deletedAt: Date;
}

View File

@ -1,14 +0,0 @@
import { DataSource, Repository } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { Attachment } from '../entities/attachment.entity';
@Injectable()
export class AttachmentRepository extends Repository<Attachment> {
constructor(private dataSource: DataSource) {
super(Attachment, dataSource.createEntityManager());
}
async findById(id: string) {
return this.findOneBy({ id: id });
}
}