File v2 - update core.file table (#17172)
For the following, I'll create the issues first
This commit is contained in:
@@ -8,17 +8,11 @@ export class FileDTO {
|
||||
id: string;
|
||||
|
||||
@Field()
|
||||
name: string;
|
||||
|
||||
@Field()
|
||||
fullPath: string;
|
||||
path: string;
|
||||
|
||||
@Field()
|
||||
size: number;
|
||||
|
||||
@Field()
|
||||
type: string;
|
||||
|
||||
@Field(() => Date, { nullable: false })
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,17 @@ import { ObjectType } from '@nestjs/graphql';
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
DeleteDateColumn,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
PrimaryGeneratedColumn,
|
||||
Relation,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { WorkspaceRelatedEntity } from 'src/engine/workspace-manager/types/workspace-related-entity';
|
||||
|
||||
@Entity('file')
|
||||
@@ -17,18 +23,30 @@ export class FileEntity extends WorkspaceRelatedEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ nullable: false })
|
||||
name: string;
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
applicationId: string;
|
||||
|
||||
@ManyToOne('ApplicationEntity', {
|
||||
onDelete: 'RESTRICT',
|
||||
})
|
||||
@JoinColumn({ name: 'applicationId' })
|
||||
application: Relation<ApplicationEntity>;
|
||||
|
||||
@Column({ nullable: false })
|
||||
fullPath: string;
|
||||
path: string;
|
||||
|
||||
@Column({ nullable: false, type: 'bigint' })
|
||||
size: number;
|
||||
|
||||
@Column({ nullable: false })
|
||||
type: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
|
||||
@DeleteDateColumn({ type: 'timestamptz' })
|
||||
deletedAt: Date | null;
|
||||
|
||||
@Column({ nullable: false, default: false })
|
||||
isStaticAsset: boolean;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { UnrecoverableError } from 'bullmq';
|
||||
import { extractFolderPathFilenameAndTypeOrThrow } from 'twenty-shared/utils';
|
||||
|
||||
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||
import { extractFolderPathAndFilename } from 'src/engine/core-modules/file/utils/extract-folderpath-and-filename.utils';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
@@ -19,7 +19,8 @@ export class FileDeletionJob {
|
||||
async handle(data: FileDeletionJobData): Promise<void> {
|
||||
const { workspaceId, fullPath } = data;
|
||||
|
||||
const { folderPath, filename } = extractFolderPathAndFilename(fullPath);
|
||||
const { folderPath, filename } =
|
||||
extractFolderPathFilenameAndTypeOrThrow(fullPath);
|
||||
|
||||
if (!filename) {
|
||||
throw new UnrecoverableError(
|
||||
|
||||
+5
-7
@@ -1,6 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { extractFolderPathFilenameAndTypeOrThrow } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
||||
@@ -8,7 +9,6 @@ import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.
|
||||
import { type FileDTO } from 'src/engine/core-modules/file/dtos/file.dto';
|
||||
import { FileEntity } from 'src/engine/core-modules/file/entities/file.entity';
|
||||
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
|
||||
import { extractFolderPathAndFilename } from 'src/engine/core-modules/file/utils/extract-folderpath-and-filename.utils';
|
||||
|
||||
import { FileService } from './file.service';
|
||||
|
||||
@@ -45,10 +45,8 @@ export class FileMetadataService {
|
||||
}
|
||||
|
||||
const createdFile = this.fileRepository.create({
|
||||
name: filename,
|
||||
fullPath: files[0].path,
|
||||
path: files[0].path,
|
||||
size: file.length,
|
||||
type: mimeType,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
@@ -69,12 +67,12 @@ export class FileMetadataService {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { folderPath, filename } = extractFolderPathAndFilename(
|
||||
file.fullPath,
|
||||
const { folderPath, filename } = extractFolderPathFilenameAndTypeOrThrow(
|
||||
file.path,
|
||||
);
|
||||
|
||||
try {
|
||||
if (file.fullPath) {
|
||||
if (file.path) {
|
||||
await this.fileService.deleteFile({
|
||||
folderPath,
|
||||
filename,
|
||||
|
||||
@@ -4,7 +4,10 @@ import { basename, dirname, extname } from 'path';
|
||||
import { type Readable } from 'stream';
|
||||
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { buildSignedPath } from 'twenty-shared/utils';
|
||||
import {
|
||||
buildSignedPath,
|
||||
extractFolderPathFilenameAndTypeOrThrow,
|
||||
} from 'twenty-shared/utils';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
|
||||
import {
|
||||
@@ -12,7 +15,6 @@ import {
|
||||
JwtTokenTypeEnum,
|
||||
} from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import { extractFolderPathAndFilename } from 'src/engine/core-modules/file/utils/extract-folderpath-and-filename.utils';
|
||||
import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
|
||||
@@ -45,7 +47,7 @@ export class FileService {
|
||||
return buildSignedPath({
|
||||
path: url,
|
||||
token: this.encodeFileToken({
|
||||
filename: extractFolderPathAndFilename(url).filename,
|
||||
filename: extractFolderPathFilenameAndTypeOrThrow(url).filename,
|
||||
workspaceId,
|
||||
}),
|
||||
});
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
export function extractFolderPathAndFilename(fullPath: string): {
|
||||
folderPath: string;
|
||||
filename: string;
|
||||
} {
|
||||
if (!fullPath || typeof fullPath !== 'string') {
|
||||
throw new Error('Invalid fullPath provided');
|
||||
}
|
||||
const parts = fullPath.split('/');
|
||||
const filename = parts.pop() || '';
|
||||
const folderPath = parts.join('/');
|
||||
|
||||
return { folderPath, filename };
|
||||
}
|
||||
+7
-4
@@ -4,13 +4,16 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { render, toPlainText } from '@react-email/render';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { reactMarkupFromJSON } from 'twenty-emails';
|
||||
import { isDefined, isValidUuid } from 'twenty-shared/utils';
|
||||
import {
|
||||
extractFolderPathFilenameAndTypeOrThrow,
|
||||
isDefined,
|
||||
isValidUuid,
|
||||
} from 'twenty-shared/utils';
|
||||
import { In, type Repository } from 'typeorm';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FileEntity } from 'src/engine/core-modules/file/entities/file.entity';
|
||||
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||
import { extractFolderPathAndFilename } from 'src/engine/core-modules/file/utils/extract-folderpath-and-filename.utils';
|
||||
import {
|
||||
SendEmailToolException,
|
||||
SendEmailToolExceptionCode,
|
||||
@@ -154,8 +157,8 @@ export class SendEmailTool implements Tool {
|
||||
for (const fileMetadata of files) {
|
||||
const fileEntity = fileEntityMap.get(fileMetadata.id)!;
|
||||
|
||||
const { folderPath, filename } = extractFolderPathAndFilename(
|
||||
fileEntity.fullPath,
|
||||
const { folderPath, filename } = extractFolderPathFilenameAndTypeOrThrow(
|
||||
fileEntity.path,
|
||||
);
|
||||
|
||||
const stream = await this.fileService.getFileStream(
|
||||
|
||||
Reference in New Issue
Block a user