mirror of
https://github.com/docmost/docmost.git
synced 2026-05-10 00:13:36 +08:00
Merge branch 'main' into perm-x
This commit is contained in:
@@ -30,9 +30,9 @@
|
||||
"test:e2e": "jest --config test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/google": "^3.0.9",
|
||||
"@ai-sdk/openai": "^3.0.11",
|
||||
"@ai-sdk/openai-compatible": "^2.0.12",
|
||||
"@ai-sdk/google": "^3.0.29",
|
||||
"@ai-sdk/openai": "^3.0.29",
|
||||
"@ai-sdk/openai-compatible": "^2.0.30",
|
||||
"@aws-sdk/client-s3": "3.982.0",
|
||||
"@aws-sdk/lib-storage": "3.982.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.982.0",
|
||||
@@ -61,11 +61,11 @@
|
||||
"@react-email/components": "1.0.7",
|
||||
"@react-email/render": "2.0.4",
|
||||
"@socket.io/redis-adapter": "^8.3.0",
|
||||
"ai": "^6.0.37",
|
||||
"ai-sdk-ollama": "^3.1.1",
|
||||
"ai": "^6.0.86",
|
||||
"ai-sdk-ollama": "^3.7.0",
|
||||
"bcrypt": "^6.0.0",
|
||||
"bullmq": "^5.65.0",
|
||||
"cache-manager": "^7.2.7",
|
||||
"cache-manager": "^7.2.8",
|
||||
"cheerio": "^1.1.2",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.3",
|
||||
@@ -102,7 +102,6 @@
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.2",
|
||||
"sanitize-filename-ts": "1.0.2",
|
||||
"sharp": "0.34.3",
|
||||
"socket.io": "^4.8.3",
|
||||
"stripe": "^17.5.0",
|
||||
"tmp-promise": "^3.0.3",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { MultipartFile } from '@fastify/multipart';
|
||||
import * as path from 'path';
|
||||
import { AttachmentType } from './attachment.constants';
|
||||
import { sanitizeFileName } from '../../common/helpers';
|
||||
import * as sharp from 'sharp';
|
||||
import { getMimeType } from '../../common/helpers';
|
||||
|
||||
export interface PreparedFile {
|
||||
buffer?: Buffer;
|
||||
@@ -41,7 +41,7 @@ export async function prepareFile(
|
||||
fileName,
|
||||
fileSize,
|
||||
fileExtension,
|
||||
mimeType: file.mimetype,
|
||||
mimeType: getMimeType(file.filename),
|
||||
multiPartFile: file,
|
||||
};
|
||||
} catch (error) {
|
||||
@@ -77,51 +77,3 @@ export function getAttachmentFolderPath(
|
||||
}
|
||||
|
||||
export const validAttachmentTypes = Object.values(AttachmentType);
|
||||
|
||||
export async function compressAndResizeIcon(
|
||||
buffer: Buffer,
|
||||
attachmentType?: AttachmentType,
|
||||
): Promise<Buffer> {
|
||||
try {
|
||||
let sharpInstance = sharp(buffer);
|
||||
const metadata = await sharpInstance.metadata();
|
||||
|
||||
const targetWidth = 300;
|
||||
const targetHeight = 300;
|
||||
|
||||
// Only resize if image is larger than target dimensions
|
||||
if (metadata.width > targetWidth || metadata.height > targetHeight) {
|
||||
sharpInstance = sharpInstance.resize(targetWidth, targetHeight, {
|
||||
fit: 'inside',
|
||||
withoutEnlargement: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Handle based on original format
|
||||
if (metadata.format === 'png') {
|
||||
// Only flatten avatars to remove transparency
|
||||
if (attachmentType === AttachmentType.Avatar) {
|
||||
sharpInstance = sharpInstance.flatten({
|
||||
background: { r: 255, g: 255, b: 255 },
|
||||
});
|
||||
}
|
||||
|
||||
return await sharpInstance
|
||||
.png({
|
||||
quality: 85,
|
||||
compressionLevel: 6,
|
||||
})
|
||||
.toBuffer();
|
||||
} else {
|
||||
return await sharpInstance
|
||||
.jpeg({
|
||||
quality: 85,
|
||||
progressive: true,
|
||||
mozjpeg: true,
|
||||
})
|
||||
.toBuffer();
|
||||
}
|
||||
} catch (err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import { Readable } from 'stream';
|
||||
import { StorageService } from '../../../integrations/storage/storage.service';
|
||||
import { MultipartFile } from '@fastify/multipart';
|
||||
import {
|
||||
compressAndResizeIcon,
|
||||
getAttachmentFolderPath,
|
||||
PreparedFile,
|
||||
prepareFile,
|
||||
@@ -154,12 +153,6 @@ export class AttachmentService {
|
||||
const preparedFile: PreparedFile = await prepareFile(filePromise);
|
||||
validateFileType(preparedFile.fileExtension, validImageExtensions);
|
||||
|
||||
const processedBuffer = await compressAndResizeIcon(
|
||||
preparedFile.buffer,
|
||||
type,
|
||||
);
|
||||
preparedFile.buffer = processedBuffer;
|
||||
preparedFile.fileSize = processedBuffer.length;
|
||||
preparedFile.fileName = uuid4() + preparedFile.fileExtension;
|
||||
|
||||
const filePath = `${getAttachmentFolderPath(type, workspaceId)}/${preparedFile.fileName}`;
|
||||
|
||||
@@ -1,55 +1,6 @@
|
||||
import {
|
||||
ApiKeys,
|
||||
Attachments,
|
||||
AuthAccounts,
|
||||
AuthProviders,
|
||||
Backlinks,
|
||||
Billing,
|
||||
Comments,
|
||||
FileTasks,
|
||||
Groups,
|
||||
GroupUsers,
|
||||
Notifications,
|
||||
PageAccess,
|
||||
PageHistory,
|
||||
PagePermissions,
|
||||
Pages,
|
||||
Shares,
|
||||
SpaceMembers,
|
||||
Spaces,
|
||||
UserMfa,
|
||||
Users,
|
||||
UserTokens,
|
||||
Watchers,
|
||||
WorkspaceInvitations,
|
||||
Workspaces,
|
||||
} from '@docmost/db/types/db';
|
||||
import { DB } from '@docmost/db/types/db';
|
||||
import { PageEmbeddings } from '@docmost/db/types/embeddings.types';
|
||||
|
||||
export interface DbInterface {
|
||||
attachments: Attachments;
|
||||
authAccounts: AuthAccounts;
|
||||
authProviders: AuthProviders;
|
||||
backlinks: Backlinks;
|
||||
billing: Billing;
|
||||
comments: Comments;
|
||||
fileTasks: FileTasks;
|
||||
groups: Groups;
|
||||
groupUsers: GroupUsers;
|
||||
notifications: Notifications;
|
||||
pageAccess: PageAccess;
|
||||
export interface DbInterface extends DB {
|
||||
pageEmbeddings: PageEmbeddings;
|
||||
pageHistory: PageHistory;
|
||||
pagePermissions: PagePermissions;
|
||||
pages: Pages;
|
||||
shares: Shares;
|
||||
spaceMembers: SpaceMembers;
|
||||
spaces: Spaces;
|
||||
userMfa: UserMfa;
|
||||
users: Users;
|
||||
userTokens: UserTokens;
|
||||
watchers: Watchers;
|
||||
workspaceInvitations: WorkspaceInvitations;
|
||||
workspaces: Workspaces;
|
||||
apiKeys: ApiKeys;
|
||||
}
|
||||
|
||||
+1
-1
Submodule apps/server/src/ee updated: ed557b4bfc...f6791125e3
@@ -91,7 +91,6 @@ export class EnvironmentVariables {
|
||||
@ValidateIf((obj) => obj.SEARCH_DRIVER === 'typesense')
|
||||
TYPESENSE_URL: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.SEARCH_DRIVER === 'typesense')
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@@ -110,18 +109,14 @@ export class EnvironmentVariables {
|
||||
AI_DRIVER: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.AI_DRIVER)
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
AI_EMBEDDING_MODEL: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.AI_EMBEDDING_DIMENSION)
|
||||
@IsIn(['768', '1024', '1536', '2000', '3072'])
|
||||
@IsString()
|
||||
AI_EMBEDDING_DIMENSION: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.AI_DRIVER)
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@@ -145,13 +140,11 @@ export class EnvironmentVariables {
|
||||
@IsUrl({ protocols: ['http', 'https'], require_tld: false })
|
||||
OPENAI_API_URL: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.AI_DRIVER && obj.AI_DRIVER === 'gemini')
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
GEMINI_API_KEY: string;
|
||||
|
||||
@IsOptional()
|
||||
@ValidateIf((obj) => obj.AI_DRIVER && obj.AI_DRIVER === 'ollama')
|
||||
@IsUrl({ protocols: ['http', 'https'], require_tld: false })
|
||||
OLLAMA_API_URL: string;
|
||||
|
||||
Reference in New Issue
Block a user