Restructure directories of data

This commit is contained in:
Hakan Shehu
2024-10-23 21:36:53 +02:00
parent cc6dc3d940
commit f1a853f83b
12 changed files with 75 additions and 119 deletions

View File

@@ -85,12 +85,11 @@ export const getFileIcon = (mimeType: string) => {
};
export const getFileUrl = (
accountId: string,
workspaceId: string,
userId: string,
fileId: string,
extension: string,
) => {
return `local-file://${accountId}/${workspaceId}/${fileId}${extension}`;
return `local-file://${userId}/${fileId}${extension}`;
};
const friendlyNameMapping: Record<string, string> = {

View File

@@ -1,20 +1,15 @@
import { app, net } from 'electron';
import { net } from 'electron';
import path from 'path';
import fs from 'fs';
import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client';
import { getAccountAvatarsDirectoryPath } from '@/main/utils';
class AvatarManager {
private readonly appPath: string;
constructor() {
this.appPath = app.getPath('userData');
}
public async handleAvatarRequest(request: Request): Promise<Response> {
const url = request.url.replace('avatar://', '');
const [accountId, avatarId] = url.split('/');
const avatarsDir = path.join(this.appPath, accountId, 'avatars');
const avatarsDir = getAccountAvatarsDirectoryPath(accountId);
const avatarPath = path.join(avatarsDir, `${avatarId}.jpeg`);
const avatarLocalUrl = `file://${avatarPath}`;

View File

@@ -1,5 +1,3 @@
import { app } from 'electron';
import path from 'path';
import fs from 'fs';
import { Kysely, Migration, Migrator, SqliteDialect } from 'kysely';
import { AppDatabaseSchema } from '@/main/data/app/schema';
@@ -7,9 +5,9 @@ import { WorkspaceDatabaseSchema } from '@/main/data/workspace/schema';
import { buildSqlite } from '@/main/data/utils';
import { appDatabaseMigrations } from '@/main/data/app/migrations';
import { workspaceDatabaseMigrations } from '@/main/data/workspace/migrations';
import { appDatabasePath, getWorkspaceDirectoryPath } from '@/main/utils';
class DatabaseManager {
private readonly appPath: string;
private initPromise: Promise<void> | null = null;
private readonly workspaceDatabases: Map<
string,
@@ -19,10 +17,8 @@ class DatabaseManager {
public readonly appDatabase: Kysely<AppDatabaseSchema>;
constructor() {
this.appPath = app.getPath('userData');
const dialect = new SqliteDialect({
database: buildSqlite(`${this.appPath}/app.db`),
database: buildSqlite(appDatabasePath),
});
this.appDatabase = new Kysely<AppDatabaseSchema>({ dialect });
@@ -56,64 +52,17 @@ class DatabaseManager {
return null;
}
const workspaceDatabase = await this.initWorkspaceDatabase(
workspace.account_id,
workspace.workspace_id,
);
const workspaceDatabase = await this.initWorkspaceDatabase(userId);
this.workspaceDatabases.set(userId, workspaceDatabase);
return workspaceDatabase;
}
public async deleteAccountData(accountId: string): Promise<void> {
await this.waitForInit();
const workspaces = await this.appDatabase
.selectFrom('workspaces')
.selectAll()
.where('account_id', '=', accountId)
.execute();
for (const workspace of workspaces) {
await this.deleteWorkspaceDatabase(
accountId,
workspace.workspace_id,
workspace.user_id,
);
}
await this.appDatabase
.deleteFrom('workspaces')
.where('account_id', '=', accountId)
.execute();
const accountDir = path.join(this.appPath, accountId);
if (fs.existsSync(accountDir)) {
fs.rmSync(accountDir, { recursive: true, force: true });
}
}
public async deleteWorkspaceDatabase(
accountId: string,
workspaceId: string,
userId: string,
): Promise<void> {
public async deleteWorkspaceDatabase(userId: string): Promise<void> {
await this.waitForInit();
if (this.workspaceDatabases.has(userId)) {
this.workspaceDatabases.delete(userId);
}
const workspaceDir = path.join(
this.appPath,
accountId,
'workspaces',
workspaceId,
);
if (fs.existsSync(workspaceDir)) {
fs.rmSync(workspaceDir, { recursive: true, force: true });
}
}
private async waitForInit(): Promise<void> {
@@ -129,13 +78,12 @@ class DatabaseManager {
const workspaces = await this.appDatabase
.selectFrom('workspaces')
.selectAll()
.select('user_id')
.execute();
for (const workspace of workspaces) {
const workspaceDatabase = await this.initWorkspaceDatabase(
workspace.account_id,
workspace.workspace_id,
workspace.user_id,
);
this.workspaceDatabases.set(workspace.user_id, workspaceDatabase);
@@ -143,15 +91,9 @@ class DatabaseManager {
}
private async initWorkspaceDatabase(
accountId: string,
workspaceId: string,
userId: string,
): Promise<Kysely<WorkspaceDatabaseSchema>> {
const workspaceDir = path.join(
this.appPath,
accountId,
'workspaces',
workspaceId,
);
const workspaceDir = getWorkspaceDirectoryPath(userId);
if (!fs.existsSync(workspaceDir)) {
fs.mkdirSync(workspaceDir, {

View File

@@ -11,18 +11,13 @@ import { databaseManager } from './data/database-manager';
import { httpClient } from '@/lib/http-client';
import { LocalNodeAttributes } from '@/types/nodes';
import { mediator } from '@/main/mediator';
import { getWorkspaceFilesDirectoryPath } from '@/main/utils';
class FileManager {
private readonly appPath: string;
constructor() {
this.appPath = app.getPath('userData');
}
public async handleFileRequest(request: Request): Promise<Response> {
const url = request.url.replace('local-file://', '');
const [accountId, workspaceId, file] = url.split('/');
const filesDir = this.getWorkspaceFilesDir(accountId, workspaceId);
const [userId, file] = url.split('/');
const filesDir = getWorkspaceFilesDirectoryPath(userId);
const filePath = path.join(filesDir, file);
if (fs.existsSync(filePath)) {
@@ -37,10 +32,9 @@ class FileManager {
filePath: string,
fileId: string,
fileExtension: string,
accountId: string,
workspaceId: string,
userId: string,
): void {
const filesDir = this.getWorkspaceFilesDir(accountId, workspaceId);
const filesDir = getWorkspaceFilesDirectoryPath(userId);
if (!fs.existsSync(filesDir)) {
fs.mkdirSync(filesDir, { recursive: true });
@@ -70,11 +64,7 @@ class FileManager {
return;
}
const filesDir = this.getWorkspaceFilesDir(
credentials.accountId,
credentials.workspaceId,
);
const filesDir = getWorkspaceFilesDirectoryPath(credentials.userId);
for (const upload of uploads) {
if (upload.retry_count >= 5) {
await workspaceDatabase
@@ -175,10 +165,10 @@ class FileManager {
return;
}
const filesDir = this.getWorkspaceFilesDir(
credentials.accountId,
credentials.workspaceId,
);
const filesDir = getWorkspaceFilesDirectoryPath(credentials.userId);
if (!fs.existsSync(filesDir)) {
fs.mkdirSync(filesDir, { recursive: true });
}
for (const download of downloads) {
const file = await workspaceDatabase
@@ -257,13 +247,6 @@ class FileManager {
},
]);
}
private getWorkspaceFilesDir(accountId: string, workspaceId: string): string {
const accountDir = path.join(this.appPath, accountId);
const workspaceDir = path.join(accountDir, 'workspaces', workspaceId);
const filesDir = path.join(workspaceDir, 'files');
return filesDir;
}
}
export const fileManager = new FileManager();

View File

@@ -31,13 +31,7 @@ export class FileCreateMutationHandler
}
const id = generateId(IdType.File);
fileManager.copyFileToWorkspace(
filePath,
id,
extension,
input.accountId,
input.workspaceId,
);
fileManager.copyFileToWorkspace(filePath, id, extension, input.userId);
await workspaceDatabase.transaction().execute(async (tx) => {
await tx

View File

@@ -30,8 +30,6 @@ export class LogoutMutationHandler
.where('id', '=', input.accountId)
.execute();
await databaseManager.deleteAccountData(input.accountId);
return {
output: {
success: true,

View File

@@ -1,8 +1,13 @@
import fs from 'fs';
import { httpClient } from '@/lib/http-client';
import { databaseManager } from '@/main/data/database-manager';
import { ServerSyncResponse } from '@/types/sync';
import { WorkspaceCredentials } from '@/types/workspaces';
import { fileManager } from '@/main/file-manager';
import {
getAccountAvatarsDirectoryPath,
getWorkspaceDirectoryPath,
} from '@/main/utils';
const EVENT_LOOP_INTERVAL = 1000;
@@ -62,11 +67,35 @@ class Synchronizer {
return;
}
await databaseManager.deleteAccountData(account.id);
const workspaces = await databaseManager.appDatabase
.selectFrom('workspaces')
.selectAll()
.where('account_id', '=', account.id)
.execute();
for (const workspace of workspaces) {
await databaseManager.deleteWorkspaceDatabase(workspace.user_id);
const workspaceDir = getWorkspaceDirectoryPath(workspace.user_id);
if (fs.existsSync(workspaceDir)) {
fs.rmSync(workspaceDir, { recursive: true });
}
}
const avatarsDir = getAccountAvatarsDirectoryPath(account.id);
if (fs.existsSync(avatarsDir)) {
fs.rmSync(avatarsDir, { recursive: true });
}
await databaseManager.appDatabase
.deleteFrom('accounts')
.where('id', '=', account.id)
.execute();
await databaseManager.appDatabase
.deleteFrom('servers')
.where('domain', '=', account.domain)
.execute();
} catch (error) {
// console.log('error', error);
}

18
desktop/src/main/utils.ts Normal file
View File

@@ -0,0 +1,18 @@
import { app } from 'electron';
import path from 'path';
export const appPath = app.getPath('userData');
export const appDatabasePath = path.join(appPath, 'app.db');
export const getWorkspaceDirectoryPath = (userId: string): string => {
return path.join(appPath, 'workspaces', userId);
};
export const getWorkspaceFilesDirectoryPath = (userId: string): string => {
return path.join(getWorkspaceDirectoryPath(userId), 'files');
};
export const getAccountAvatarsDirectoryPath = (accountId: string): string => {
return path.join(appPath, 'avatars', accountId);
};

View File

@@ -1,8 +1,6 @@
export type FileCreateMutationInput = {
type: 'file_create';
userId: string;
workspaceId: string;
accountId: string;
parentId: string;
filePath: string;
};

View File

@@ -24,7 +24,7 @@ export const FileThumbnail = ({
const workspace = useWorkspace();
if (downloadProgress === 100 && mimeType.startsWith('image')) {
const url = getFileUrl(workspace.accountId, workspace.id, id, extension);
const url = getFileUrl(workspace.userId, id, extension);
return (
<img
src={url}

View File

@@ -14,7 +14,7 @@ export const FilePreviewImage = ({
extension,
}: FilePreviewImageProps) => {
const workspace = useWorkspace();
const url = getFileUrl(workspace.accountId, workspace.id, id, extension);
const url = getFileUrl(workspace.userId, id, extension);
return (
<img

View File

@@ -14,7 +14,7 @@ export const FilePreviewVideo = ({
extension,
}: FilePreviewVideoProps) => {
const workspace = useWorkspace();
const url = getFileUrl(workspace.accountId, workspace.id, id, extension);
const url = getFileUrl(workspace.userId, id, extension);
return <video controls src={url} className="h-full w-full object-contain" />;
};