mirror of
https://github.com/colanode/colanode.git
synced 2025-12-29 00:25:03 +01:00
Restructure directories of data
This commit is contained in:
@@ -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> = {
|
||||
|
||||
@@ -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}`;
|
||||
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,8 +30,6 @@ export class LogoutMutationHandler
|
||||
.where('id', '=', input.accountId)
|
||||
.execute();
|
||||
|
||||
await databaseManager.deleteAccountData(input.accountId);
|
||||
|
||||
return {
|
||||
output: {
|
||||
success: true,
|
||||
|
||||
@@ -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
18
desktop/src/main/utils.ts
Normal 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);
|
||||
};
|
||||
@@ -1,8 +1,6 @@
|
||||
export type FileCreateMutationInput = {
|
||||
type: 'file_create';
|
||||
userId: string;
|
||||
workspaceId: string;
|
||||
accountId: string;
|
||||
parentId: string;
|
||||
filePath: string;
|
||||
};
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user