mirror of
https://github.com/colanode/colanode.git
synced 2025-12-16 11:47:47 +01:00
Refactor workspaces and accounts databases and routes locally
This commit is contained in:
@@ -16,7 +16,7 @@ import { updateElectronApp, UpdateSourceType } from 'update-electron-app';
|
||||
import { eventBus } from '@colanode/client/lib';
|
||||
import { MutationInput, MutationMap } from '@colanode/client/mutations';
|
||||
import { QueryInput, QueryMap } from '@colanode/client/queries';
|
||||
import { TempFile } from '@colanode/client/types';
|
||||
import { TempFile, ThemeMode, WindowSize } from '@colanode/client/types';
|
||||
import {
|
||||
createDebugger,
|
||||
extractFileSubtype,
|
||||
@@ -49,13 +49,19 @@ updateElectronApp({
|
||||
const createWindow = async () => {
|
||||
await app.migrate();
|
||||
|
||||
const themeMode = (await app.metadata.get('theme.mode'))?.value;
|
||||
if (themeMode) {
|
||||
const themeMetadata = await app.metadata.get('app', 'theme.mode');
|
||||
if (themeMetadata) {
|
||||
const themeMode = JSON.parse(themeMetadata.value) as ThemeMode;
|
||||
nativeTheme.themeSource = themeMode;
|
||||
}
|
||||
|
||||
let windowSize: WindowSize | undefined;
|
||||
const windowSizeMetadata = await app.metadata.get('app', 'window.size');
|
||||
if (windowSizeMetadata) {
|
||||
windowSize = JSON.parse(windowSizeMetadata.value) as WindowSize;
|
||||
}
|
||||
|
||||
// Create the browser window.
|
||||
let windowSize = (await app.metadata.get('window.size'))?.value;
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: windowSize?.width ?? 1200,
|
||||
height: windowSize?.height ?? 800,
|
||||
@@ -81,7 +87,7 @@ const createWindow = async () => {
|
||||
fullscreen: false,
|
||||
};
|
||||
|
||||
app.metadata.set('window.size', windowSize);
|
||||
app.metadata.set('app', 'window.size', JSON.stringify(windowSize));
|
||||
});
|
||||
|
||||
mainWindow.on('enter-full-screen', () => {
|
||||
@@ -91,7 +97,7 @@ const createWindow = async () => {
|
||||
fullscreen: true,
|
||||
};
|
||||
|
||||
app.metadata.set('window.size', windowSize);
|
||||
app.metadata.set('app', 'window.size', JSON.stringify(windowSize));
|
||||
});
|
||||
|
||||
mainWindow.on('leave-full-screen', () => {
|
||||
@@ -101,7 +107,7 @@ const createWindow = async () => {
|
||||
fullscreen: false,
|
||||
};
|
||||
|
||||
app.metadata.set('window.size', windowSize);
|
||||
app.metadata.set('app', 'window.size', JSON.stringify(windowSize));
|
||||
});
|
||||
|
||||
// and load the index.html of the app.
|
||||
@@ -118,12 +124,13 @@ const createWindow = async () => {
|
||||
const subscriptionId = eventBus.subscribe((event) => {
|
||||
mainWindow.webContents.send('event', event);
|
||||
if (
|
||||
event.type === 'app.metadata.updated' &&
|
||||
event.type === 'metadata.updated' &&
|
||||
event.metadata.key === 'theme.mode'
|
||||
) {
|
||||
nativeTheme.themeSource = event.metadata.value;
|
||||
const themeMode = JSON.parse(event.metadata.value) as ThemeMode;
|
||||
nativeTheme.themeSource = themeMode;
|
||||
} else if (
|
||||
event.type === 'app.metadata.deleted' &&
|
||||
event.type === 'metadata.deleted' &&
|
||||
event.metadata.key === 'theme.mode'
|
||||
) {
|
||||
nativeTheme.themeSource = 'system';
|
||||
|
||||
@@ -31,8 +31,8 @@ export class AppBadge {
|
||||
return;
|
||||
}
|
||||
|
||||
const accounts = this.app.getAccounts();
|
||||
if (accounts.length === 0) {
|
||||
const workspaces = this.app.getWorkspaces();
|
||||
if (workspaces.length === 0) {
|
||||
electronApp?.dock?.setBadge('');
|
||||
return;
|
||||
}
|
||||
@@ -40,14 +40,10 @@ export class AppBadge {
|
||||
let hasUnread = false;
|
||||
let unreadCount = 0;
|
||||
|
||||
for (const account of accounts) {
|
||||
const workspaces = account.getWorkspaces();
|
||||
|
||||
for (const workspace of workspaces) {
|
||||
const radarData = workspace.radar.getData();
|
||||
hasUnread = hasUnread || radarData.state.hasUnread;
|
||||
unreadCount = unreadCount + radarData.state.unreadCount;
|
||||
}
|
||||
for (const workspace of workspaces) {
|
||||
const radarData = workspace.radar.getData();
|
||||
hasUnread = hasUnread || radarData.state.hasUnread;
|
||||
unreadCount = unreadCount + radarData.state.unreadCount;
|
||||
}
|
||||
|
||||
if (unreadCount > 0) {
|
||||
|
||||
@@ -5,48 +5,29 @@ import { PathService } from '@colanode/client/services';
|
||||
|
||||
export class DesktopPathService implements PathService {
|
||||
private readonly nativePath = path;
|
||||
|
||||
private readonly appPath = app.getPath('userData');
|
||||
private readonly appDatabasePath = this.nativePath.join(
|
||||
this.appPath,
|
||||
'app.db'
|
||||
);
|
||||
private readonly accountsDirectoryPath = this.nativePath.join(
|
||||
private readonly avatarsPath = this.nativePath.join(this.appPath, 'avatars');
|
||||
private readonly workspacesPath = this.nativePath.join(
|
||||
this.appPath,
|
||||
'accounts'
|
||||
'workspaces'
|
||||
);
|
||||
|
||||
private getAccountDirectoryPath(accountId: string): string {
|
||||
return this.nativePath.join(this.accountsDirectoryPath, accountId);
|
||||
private getWorkspaceDirectoryPath(userId: string): string {
|
||||
return this.nativePath.join(this.workspacesPath, userId);
|
||||
}
|
||||
|
||||
private getWorkspaceDirectoryPath(
|
||||
accountId: string,
|
||||
workspaceId: string
|
||||
): string {
|
||||
private getWorkspaceFilesDirectoryPath(userId: string): string {
|
||||
return this.nativePath.join(
|
||||
this.getAccountDirectoryPath(accountId),
|
||||
'workspaces',
|
||||
workspaceId
|
||||
);
|
||||
}
|
||||
|
||||
private getWorkspaceFilesDirectoryPath(
|
||||
accountId: string,
|
||||
workspaceId: string
|
||||
): string {
|
||||
return this.nativePath.join(
|
||||
this.getWorkspaceDirectoryPath(accountId, workspaceId),
|
||||
this.getWorkspaceDirectoryPath(userId),
|
||||
'files'
|
||||
);
|
||||
}
|
||||
|
||||
private getAccountAvatarsDirectoryPath(accountId: string): string {
|
||||
return this.nativePath.join(
|
||||
this.getAccountDirectoryPath(accountId),
|
||||
'avatars'
|
||||
);
|
||||
}
|
||||
|
||||
private getAssetsSourcePath(): string {
|
||||
if (app.isPackaged) {
|
||||
return this.nativePath.join(process.resourcesPath, 'assets');
|
||||
@@ -62,67 +43,48 @@ export class DesktopPathService implements PathService {
|
||||
return this.appDatabasePath;
|
||||
}
|
||||
|
||||
public get accounts(): string {
|
||||
return this.accountsDirectoryPath;
|
||||
}
|
||||
|
||||
public get temp(): string {
|
||||
return this.nativePath.join(this.appPath, 'temp');
|
||||
}
|
||||
|
||||
public get avatars(): string {
|
||||
return this.avatarsPath;
|
||||
}
|
||||
|
||||
public tempFile(name: string): string {
|
||||
return this.nativePath.join(this.appPath, 'temp', name);
|
||||
}
|
||||
|
||||
public account(accountId: string): string {
|
||||
return this.getAccountDirectoryPath(accountId);
|
||||
public avatar(avatarId: string): string {
|
||||
return this.nativePath.join(this.avatarsPath, avatarId + '.jpeg');
|
||||
}
|
||||
|
||||
public accountDatabase(accountId: string): string {
|
||||
public workspace(userId: string): string {
|
||||
return this.getWorkspaceDirectoryPath(userId);
|
||||
}
|
||||
|
||||
public workspaceDatabase(userId: string): string {
|
||||
return this.nativePath.join(
|
||||
this.getAccountDirectoryPath(accountId),
|
||||
'account.db'
|
||||
);
|
||||
}
|
||||
|
||||
public workspace(accountId: string, workspaceId: string): string {
|
||||
return this.getWorkspaceDirectoryPath(accountId, workspaceId);
|
||||
}
|
||||
|
||||
public workspaceDatabase(accountId: string, workspaceId: string): string {
|
||||
return this.nativePath.join(
|
||||
this.getWorkspaceDirectoryPath(accountId, workspaceId),
|
||||
this.getWorkspaceDirectoryPath(userId),
|
||||
'workspace.db'
|
||||
);
|
||||
}
|
||||
|
||||
public workspaceFiles(accountId: string, workspaceId: string): string {
|
||||
return this.getWorkspaceFilesDirectoryPath(accountId, workspaceId);
|
||||
public workspaceFiles(userId: string): string {
|
||||
return this.getWorkspaceFilesDirectoryPath(userId);
|
||||
}
|
||||
|
||||
public workspaceFile(
|
||||
accountId: string,
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
fileId: string,
|
||||
extension: string
|
||||
): string {
|
||||
return this.nativePath.join(
|
||||
this.getWorkspaceFilesDirectoryPath(accountId, workspaceId),
|
||||
this.getWorkspaceFilesDirectoryPath(userId),
|
||||
fileId + extension
|
||||
);
|
||||
}
|
||||
|
||||
public accountAvatars(accountId: string): string {
|
||||
return this.getAccountAvatarsDirectoryPath(accountId);
|
||||
}
|
||||
|
||||
public accountAvatar(accountId: string, avatarId: string): string {
|
||||
return this.nativePath.join(
|
||||
this.getAccountAvatarsDirectoryPath(accountId),
|
||||
avatarId + '.jpeg'
|
||||
);
|
||||
}
|
||||
|
||||
public dirname(dir: string): string {
|
||||
return this.nativePath.dirname(dir);
|
||||
}
|
||||
|
||||
@@ -3,39 +3,22 @@ import { Paths, File, Directory } from 'expo-file-system';
|
||||
import { PathService } from '@colanode/client/services';
|
||||
|
||||
export class MobilePathService implements PathService {
|
||||
private readonly accountsDirectoryPath = new Directory(
|
||||
private readonly avatarsDirectoryPath = new Directory(
|
||||
Paths.document,
|
||||
'accounts'
|
||||
'avatars'
|
||||
);
|
||||
|
||||
private getAccountDirectoryPath(accountId: string): string {
|
||||
return new Directory(this.accountsDirectoryPath, accountId).uri;
|
||||
private readonly workspacesDirectoryPath = new Directory(
|
||||
Paths.document,
|
||||
'workspaces'
|
||||
);
|
||||
|
||||
private getWorkspaceDirectoryPath(userId: string): string {
|
||||
return new Directory(this.workspacesDirectoryPath, userId).uri;
|
||||
}
|
||||
|
||||
private getWorkspaceDirectoryPath(
|
||||
accountId: string,
|
||||
workspaceId: string
|
||||
): string {
|
||||
return new Directory(
|
||||
this.getAccountDirectoryPath(accountId),
|
||||
'workspaces',
|
||||
workspaceId
|
||||
).uri;
|
||||
}
|
||||
|
||||
private getWorkspaceFilesDirectoryPath(
|
||||
accountId: string,
|
||||
workspaceId: string
|
||||
): string {
|
||||
return new Directory(
|
||||
this.getWorkspaceDirectoryPath(accountId, workspaceId),
|
||||
'files'
|
||||
).uri;
|
||||
}
|
||||
|
||||
private getAccountAvatarsDirectoryPath(accountId: string): string {
|
||||
return new Directory(this.getAccountDirectoryPath(accountId), 'avatars')
|
||||
.uri;
|
||||
private getWorkspaceFilesDirectoryPath(userId: string): string {
|
||||
return new Directory(this.getWorkspaceDirectoryPath(userId), 'files').uri;
|
||||
}
|
||||
|
||||
private getAssetsSourcePath(): string {
|
||||
@@ -50,64 +33,45 @@ export class MobilePathService implements PathService {
|
||||
return new File(Paths.document, 'app.db').uri;
|
||||
}
|
||||
|
||||
public get accounts(): string {
|
||||
return this.accountsDirectoryPath.uri;
|
||||
public get avatars(): string {
|
||||
return this.avatarsDirectoryPath.uri;
|
||||
}
|
||||
|
||||
public get temp(): string {
|
||||
return new Directory(Paths.document, 'temp').uri;
|
||||
}
|
||||
|
||||
public avatar(avatarId: string): string {
|
||||
return new File(this.avatarsDirectoryPath, avatarId + '.jpeg').uri;
|
||||
}
|
||||
|
||||
public tempFile(name: string): string {
|
||||
return new File(Paths.document, 'temp', name).uri;
|
||||
}
|
||||
|
||||
public account(accountId: string): string {
|
||||
return this.getAccountDirectoryPath(accountId);
|
||||
public workspace(userId: string): string {
|
||||
return this.getWorkspaceDirectoryPath(userId);
|
||||
}
|
||||
|
||||
public accountDatabase(accountId: string): string {
|
||||
return new File(this.getAccountDirectoryPath(accountId), 'account.db').uri;
|
||||
public workspaceDatabase(userId: string): string {
|
||||
return new File(this.getWorkspaceDirectoryPath(userId), 'workspace.db').uri;
|
||||
}
|
||||
|
||||
public workspace(accountId: string, workspaceId: string): string {
|
||||
return this.getWorkspaceDirectoryPath(accountId, workspaceId);
|
||||
}
|
||||
|
||||
public workspaceDatabase(accountId: string, workspaceId: string): string {
|
||||
return new File(
|
||||
this.getWorkspaceDirectoryPath(accountId, workspaceId),
|
||||
'workspace.db'
|
||||
).uri;
|
||||
}
|
||||
|
||||
public workspaceFiles(accountId: string, workspaceId: string): string {
|
||||
return this.getWorkspaceFilesDirectoryPath(accountId, workspaceId);
|
||||
public workspaceFiles(userId: string): string {
|
||||
return this.getWorkspaceFilesDirectoryPath(userId);
|
||||
}
|
||||
|
||||
public workspaceFile(
|
||||
accountId: string,
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
fileId: string,
|
||||
extension: string
|
||||
): string {
|
||||
return new File(
|
||||
this.getWorkspaceFilesDirectoryPath(accountId, workspaceId),
|
||||
this.getWorkspaceFilesDirectoryPath(userId),
|
||||
fileId + extension
|
||||
).uri;
|
||||
}
|
||||
|
||||
public accountAvatars(accountId: string): string {
|
||||
return this.getAccountAvatarsDirectoryPath(accountId);
|
||||
}
|
||||
|
||||
public accountAvatar(accountId: string, avatarId: string): string {
|
||||
return new File(
|
||||
this.getAccountAvatarsDirectoryPath(accountId),
|
||||
avatarId + '.jpeg'
|
||||
).uri;
|
||||
}
|
||||
|
||||
public dirname(path: string): string {
|
||||
const info = Paths.info(path);
|
||||
if (info.isDirectory) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export class WebFileSystem implements FileSystem {
|
||||
: new ArrayBuffer(data.byteLength);
|
||||
|
||||
if (!(data.buffer instanceof ArrayBuffer)) {
|
||||
const view = new Uint8Array<ArrayBuffer>(arrayBuffer);
|
||||
const view = new Uint8Array(arrayBuffer);
|
||||
view.set(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ import { PathService } from '@colanode/client/services';
|
||||
|
||||
export class WebPathService implements PathService {
|
||||
private readonly appPath = '';
|
||||
private readonly appDatabasePath = this.join(this.appPath, 'app.db');
|
||||
private readonly accountsDirectoryPath = this.join(this.appPath, 'accounts');
|
||||
private readonly assetsSourcePath = 'assets';
|
||||
private readonly appDatabasePath = this.join(this.appPath, 'app.db');
|
||||
private readonly avatarsPath = this.join(this.appPath, 'avatars');
|
||||
private readonly workspacesPath = this.join(this.appPath, 'workspaces');
|
||||
|
||||
public get app() {
|
||||
return this.appPath;
|
||||
@@ -14,8 +15,8 @@ export class WebPathService implements PathService {
|
||||
return this.appDatabasePath;
|
||||
}
|
||||
|
||||
public get accounts() {
|
||||
return this.accountsDirectoryPath;
|
||||
public get avatars() {
|
||||
return this.avatarsPath;
|
||||
}
|
||||
|
||||
public get temp() {
|
||||
@@ -42,44 +43,28 @@ export class WebPathService implements PathService {
|
||||
return this.join(this.appPath, 'temp', name);
|
||||
}
|
||||
|
||||
public account(accountId: string): string {
|
||||
return this.join(this.accountsDirectoryPath, accountId);
|
||||
public avatar(avatarId: string): string {
|
||||
return this.join(this.avatarsPath, avatarId + '.jpeg');
|
||||
}
|
||||
|
||||
public accountDatabase(accountId: string): string {
|
||||
return this.join(this.account(accountId), 'account.db');
|
||||
public workspace(userId: string): string {
|
||||
return this.join(this.workspacesPath, userId);
|
||||
}
|
||||
|
||||
public workspace(accountId: string, workspaceId: string): string {
|
||||
return this.join(this.account(accountId), 'workspaces', workspaceId);
|
||||
public workspaceDatabase(userId: string): string {
|
||||
return this.join(this.workspace(userId), 'workspace.db');
|
||||
}
|
||||
|
||||
public workspaceDatabase(accountId: string, workspaceId: string): string {
|
||||
return this.join(this.workspace(accountId, workspaceId), 'workspace.db');
|
||||
}
|
||||
|
||||
public workspaceFiles(accountId: string, workspaceId: string): string {
|
||||
return this.join(this.workspace(accountId, workspaceId), 'files');
|
||||
public workspaceFiles(userId: string): string {
|
||||
return this.join(this.workspace(userId), 'files');
|
||||
}
|
||||
|
||||
public workspaceFile(
|
||||
accountId: string,
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
fileId: string,
|
||||
extension: string
|
||||
): string {
|
||||
return this.join(
|
||||
this.workspaceFiles(accountId, workspaceId),
|
||||
fileId + extension
|
||||
);
|
||||
}
|
||||
|
||||
public accountAvatars(accountId: string): string {
|
||||
return this.join(this.account(accountId), 'avatars');
|
||||
}
|
||||
|
||||
public accountAvatar(accountId: string, avatarId: string): string {
|
||||
return this.join(this.accountAvatars(accountId), avatarId + '.jpeg');
|
||||
return this.join(this.workspaceFiles(userId), fileId + extension);
|
||||
}
|
||||
|
||||
public dirname(path: string): string {
|
||||
|
||||
34
package-lock.json
generated
34
package-lock.json
generated
@@ -11507,9 +11507,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/db": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/db/-/db-0.4.4.tgz",
|
||||
"integrity": "sha512-G+abJtW6jBjAwMSgbaSYuwUJFUaxTY7kb+PyT3Y6r2pr795v+QQNHe6pniQeqrLp3M5nnx3rws+XfeqoDgN/VQ==",
|
||||
"version": "0.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/db/-/db-0.4.7.tgz",
|
||||
"integrity": "sha512-SXwbqvWfBkP7VkmOcAjvy6vgKO2IjuE4jhlj2Th94f7fhFCXf/BgcAVB5ZbD59Dygt8AkeVQKRVr/k7z/D/7RQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
@@ -11556,13 +11556,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/query-db-collection": {
|
||||
"version": "0.2.25",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-db-collection/-/query-db-collection-0.2.25.tgz",
|
||||
"integrity": "sha512-Io07hIX7VLg7cO2/+Y6c9Bf2Y8xWtxt31i2lLswW2lx0sTZvK6sIpLvld8SxbMeRJHrwtXra++V0O6a1Y2ALGA==",
|
||||
"version": "0.2.28",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/query-db-collection/-/query-db-collection-0.2.28.tgz",
|
||||
"integrity": "sha512-rD+x1lVvz8BtdpEThyQiYaU8VoqlJPhPwpQEgPGhPu913AyXVDiUKu1rhQFRP6e9Zz0tXF/0kh6bFG+khov4ag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@standard-schema/spec": "^1.0.0",
|
||||
"@tanstack/db": "0.4.4"
|
||||
"@tanstack/db": "0.4.7"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/query-core": "^5.0.0",
|
||||
@@ -11570,13 +11570,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-db": {
|
||||
"version": "0.1.26",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-db/-/react-db-0.1.26.tgz",
|
||||
"integrity": "sha512-8itSp4bd+PU7/yImMn3eAcMq2AEzDVuPhJ2K5Pyqh7f9qhXlMDdxcm1K9BpZpaQJOJEcLYls6FDnaNNkyc5/hQ==",
|
||||
"version": "0.1.29",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-db/-/react-db-0.1.29.tgz",
|
||||
"integrity": "sha512-57MI8dtAIoxl0xYVbMysHZewIylxi2l3LPNS3qy9nGBGxuM0y6anu5KyR8rWYL+ylFK4nSvc86ebT569O7Vu3A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/db": "0.4.4",
|
||||
"use-sync-external-store": "^1.5.0"
|
||||
"@tanstack/db": "0.4.7",
|
||||
"use-sync-external-store": "^1.6.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8.0"
|
||||
@@ -29352,9 +29352,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
|
||||
"integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
|
||||
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
@@ -30886,8 +30886,8 @@
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@react-oauth/google": "^0.12.2",
|
||||
"@tanstack/query-db-collection": "^0.2.25",
|
||||
"@tanstack/react-db": "^0.1.26",
|
||||
"@tanstack/query-db-collection": "^0.2.28",
|
||||
"@tanstack/react-db": "^0.1.29",
|
||||
"@tanstack/react-query": "^5.87.4",
|
||||
"@tanstack/react-router": "^1.131.45",
|
||||
"@tanstack/react-virtual": "^3.13.12",
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './schema';
|
||||
export * from './migrations';
|
||||
@@ -1,11 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
import { createWorkspacesTable } from './00001-create-workspaces-table';
|
||||
import { createMetadataTable } from './00002-create-metadata-table';
|
||||
import { createAvatarsTable } from './00003-create-avatars-table';
|
||||
|
||||
export const accountDatabaseMigrations: Record<string, Migration> = {
|
||||
'00001-create-workspaces-table': createWorkspacesTable,
|
||||
'00002-create-metadata-table': createMetadataTable,
|
||||
'00003-create-avatars-table': createAvatarsTable,
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import { ColumnType, Insertable, Selectable, Updateable } from 'kysely';
|
||||
|
||||
import { WorkspaceRole } from '@colanode/core';
|
||||
|
||||
interface WorkspaceTable {
|
||||
id: ColumnType<string, string, never>;
|
||||
user_id: ColumnType<string, string, never>;
|
||||
account_id: ColumnType<string, string, never>;
|
||||
name: ColumnType<string, string, string>;
|
||||
description: ColumnType<string | null, string | null, string | null>;
|
||||
avatar: ColumnType<string | null, string | null, string | null>;
|
||||
role: ColumnType<WorkspaceRole, WorkspaceRole, WorkspaceRole>;
|
||||
storage_limit: ColumnType<string, string, string>;
|
||||
max_file_size: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
}
|
||||
|
||||
export type SelectWorkspace = Selectable<WorkspaceTable>;
|
||||
export type CreateWorkspace = Insertable<WorkspaceTable>;
|
||||
export type UpdateWorkspace = Updateable<WorkspaceTable>;
|
||||
|
||||
interface AccountMetadataTable {
|
||||
key: ColumnType<string, string, never>;
|
||||
value: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
updated_at: ColumnType<string | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
export type SelectAccountMetadata = Selectable<AccountMetadataTable>;
|
||||
export type CreateAccountMetadata = Insertable<AccountMetadataTable>;
|
||||
export type UpdateAccountMetadata = Updateable<AccountMetadataTable>;
|
||||
|
||||
interface AvatarTable {
|
||||
id: ColumnType<string, string, never>;
|
||||
path: ColumnType<string, string, string>;
|
||||
size: ColumnType<number, number, number>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
opened_at: ColumnType<string, string, string>;
|
||||
}
|
||||
|
||||
export type SelectAvatar = Selectable<AvatarTable>;
|
||||
export type CreateAvatar = Insertable<AvatarTable>;
|
||||
export type UpdateAvatar = Updateable<AvatarTable>;
|
||||
|
||||
export interface AccountDatabaseSchema {
|
||||
workspaces: WorkspaceTable;
|
||||
metadata: AccountMetadataTable;
|
||||
avatars: AvatarTable;
|
||||
}
|
||||
@@ -12,28 +12,6 @@ export const createServersTable: Migration = {
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.addColumn('synced_at', 'text')
|
||||
.execute();
|
||||
|
||||
await db
|
||||
.insertInto('servers')
|
||||
.values([
|
||||
{
|
||||
domain: 'eu.colanode.com',
|
||||
name: 'Colanode Cloud (EU)',
|
||||
avatar: 'https://colanode.com/assets/flags/eu.svg',
|
||||
attributes: '{}',
|
||||
version: '0.2.0',
|
||||
created_at: new Date().toISOString(),
|
||||
},
|
||||
{
|
||||
domain: 'us.colanode.com',
|
||||
name: 'Colanode Cloud (US)',
|
||||
avatar: 'https://colanode.com/assets/flags/us.svg',
|
||||
attributes: '{}',
|
||||
version: '0.2.0',
|
||||
created_at: new Date().toISOString(),
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema.dropTable('servers').execute();
|
||||
|
||||
@@ -4,10 +4,12 @@ export const createMetadataTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('metadata')
|
||||
.addColumn('key', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('namespace', 'text', (col) => col.notNull())
|
||||
.addColumn('key', 'text', (col) => col.notNull())
|
||||
.addColumn('value', 'text', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.addColumn('updated_at', 'text')
|
||||
.addPrimaryKeyConstraint('pk_metadata', ['namespace', 'key'])
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
export const createDeletedTokensTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('deleted_tokens')
|
||||
.addColumn('account_id', 'text', (col) => col.notNull())
|
||||
.addColumn('token', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('server', 'text', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema.dropTable('deleted_tokens').execute();
|
||||
},
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
export const createMetadataTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('metadata')
|
||||
.addColumn('key', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('value', 'text', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.addColumn('updated_at', 'text')
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema.dropTable('metadata').execute();
|
||||
},
|
||||
};
|
||||
@@ -4,8 +4,8 @@ export const createWorkspacesTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('workspaces')
|
||||
.addColumn('id', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('user_id', 'text', (col) => col.notNull())
|
||||
.addColumn('user_id', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('workspace_id', 'text', (col) => col.notNull())
|
||||
.addColumn('account_id', 'text', (col) => col.notNull())
|
||||
.addColumn('name', 'text', (col) => col.notNull())
|
||||
.addColumn('description', 'text')
|
||||
@@ -14,6 +14,7 @@ export const createWorkspacesTable: Migration = {
|
||||
.addColumn('storage_limit', 'integer', (col) => col.notNull())
|
||||
.addColumn('max_file_size', 'integer', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.addColumn('updated_at', 'text')
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
export const dropDeletedTokensTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema.dropTable('deleted_tokens').execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema
|
||||
.createTable('deleted_tokens')
|
||||
.addColumn('account_id', 'text', (col) => col.notNull())
|
||||
.addColumn('token', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('server', 'text', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.execute();
|
||||
},
|
||||
};
|
||||
@@ -1,23 +1,23 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
import { createServersTable } from './00001-create-servers-table';
|
||||
import { createAccountsTable } from './00002-create-accounts-table';
|
||||
import { createDeletedTokensTable } from './00003-create-deleted-tokens-table';
|
||||
import { createMetadataTable } from './00004-create-metadata-table';
|
||||
import { createMetadataTable } from './00002-create-metadata-table';
|
||||
import { createAccountsTable } from './00003-create-accounts-table';
|
||||
import { createWorkspacesTable } from './00004-create-workspaces-table';
|
||||
import { createJobsTable } from './00005-create-jobs-table';
|
||||
import { createJobSchedulesTable } from './00006-create-job-schedules-table';
|
||||
import { dropDeletedTokensTable } from './00007-drop-deleted-tokens-table';
|
||||
import { createTempFilesTable } from './00008-create-temp-files-table';
|
||||
import { createTempFilesTable } from './00007-create-temp-files-table';
|
||||
import { createAvatarsTable } from './00008-create-avatars-table';
|
||||
import { createTabsTable } from './00009-create-tabs-table';
|
||||
|
||||
export const appDatabaseMigrations: Record<string, Migration> = {
|
||||
'00001-create-servers-table': createServersTable,
|
||||
'00002-create-accounts-table': createAccountsTable,
|
||||
'00003-create-deleted-tokens-table': createDeletedTokensTable,
|
||||
'00004-create-metadata-table': createMetadataTable,
|
||||
'00002-create-metadata-table': createMetadataTable,
|
||||
'00003-create-accounts-table': createAccountsTable,
|
||||
'00004-create-workspaces-table': createWorkspacesTable,
|
||||
'00005-create-jobs-table': createJobsTable,
|
||||
'00006-create-job-schedules-table': createJobSchedulesTable,
|
||||
'00007-drop-deleted-tokens-table': dropDeletedTokensTable,
|
||||
'00008-create-temp-files-table': createTempFilesTable,
|
||||
'00007-create-temp-files-table': createTempFilesTable,
|
||||
'00008-create-avatars-table': createAvatarsTable,
|
||||
'00009-create-tabs-table': createTabsTable,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ColumnType, Insertable, Selectable, Updateable } from 'kysely';
|
||||
|
||||
import { JobScheduleStatus, JobStatus } from '@colanode/client/jobs';
|
||||
import { FileSubtype } from '@colanode/core';
|
||||
import { FileSubtype, WorkspaceRole } from '@colanode/core';
|
||||
|
||||
interface ServerTable {
|
||||
domain: ColumnType<string, string, never>;
|
||||
@@ -17,6 +17,18 @@ export type SelectServer = Selectable<ServerTable>;
|
||||
export type CreateServer = Insertable<ServerTable>;
|
||||
export type UpdateServer = Updateable<ServerTable>;
|
||||
|
||||
interface MetadataTable {
|
||||
namespace: ColumnType<string, string, never>;
|
||||
key: ColumnType<string, string, never>;
|
||||
value: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
updated_at: ColumnType<string | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
export type SelectMetadata = Selectable<MetadataTable>;
|
||||
export type CreateMetadata = Insertable<MetadataTable>;
|
||||
export type UpdateMetadata = Updateable<MetadataTable>;
|
||||
|
||||
interface AccountTable {
|
||||
id: ColumnType<string, string, never>;
|
||||
server: ColumnType<string, string, never>;
|
||||
@@ -34,17 +46,6 @@ export type SelectAccount = Selectable<AccountTable>;
|
||||
export type CreateAccount = Insertable<AccountTable>;
|
||||
export type UpdateAccount = Updateable<AccountTable>;
|
||||
|
||||
interface AppMetadataTable {
|
||||
key: ColumnType<string, string, never>;
|
||||
value: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
updated_at: ColumnType<string | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
export type SelectAppMetadata = Selectable<AppMetadataTable>;
|
||||
export type CreateAppMetadata = Insertable<AppMetadataTable>;
|
||||
export type UpdateAppMetadata = Updateable<AppMetadataTable>;
|
||||
|
||||
export interface JobTableSchema {
|
||||
id: ColumnType<string, string, never>;
|
||||
queue: ColumnType<string, string, never>;
|
||||
@@ -109,12 +110,44 @@ export type SelectTab = Selectable<TabTable>;
|
||||
export type InsertTab = Insertable<TabTable>;
|
||||
export type UpdateTab = Updateable<TabTable>;
|
||||
|
||||
interface WorkspacesTable {
|
||||
user_id: ColumnType<string, string, never>;
|
||||
workspace_id: ColumnType<string, string, string>;
|
||||
account_id: ColumnType<string, string, string>;
|
||||
name: ColumnType<string, string, string>;
|
||||
description: ColumnType<string | null, string | null, string | null>;
|
||||
avatar: ColumnType<string | null, string | null, string | null>;
|
||||
role: ColumnType<WorkspaceRole, WorkspaceRole, WorkspaceRole>;
|
||||
storage_limit: ColumnType<string, string, string>;
|
||||
max_file_size: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, string>;
|
||||
updated_at: ColumnType<string | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
export type SelectWorkspace = Selectable<WorkspacesTable>;
|
||||
export type InsertWorkspace = Insertable<WorkspacesTable>;
|
||||
export type UpdateWorkspace = Updateable<WorkspacesTable>;
|
||||
|
||||
interface AvatarsTable {
|
||||
id: ColumnType<string, string, never>;
|
||||
path: ColumnType<string, string, string>;
|
||||
size: ColumnType<number, number, number>;
|
||||
created_at: ColumnType<string, string, string>;
|
||||
opened_at: ColumnType<string, string, string>;
|
||||
}
|
||||
|
||||
export type SelectAvatar = Selectable<AvatarsTable>;
|
||||
export type InsertAvatar = Insertable<AvatarsTable>;
|
||||
export type UpdateAvatar = Updateable<AvatarsTable>;
|
||||
|
||||
export interface AppDatabaseSchema {
|
||||
servers: ServerTable;
|
||||
metadata: MetadataTable;
|
||||
accounts: AccountTable;
|
||||
metadata: AppMetadataTable;
|
||||
workspaces: WorkspacesTable;
|
||||
jobs: JobTableSchema;
|
||||
job_schedules: JobScheduleTableSchema;
|
||||
temp_files: TempFileTable;
|
||||
avatars: AvatarsTable;
|
||||
tabs: TabTable;
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
export const createFileStatesTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('file_states')
|
||||
.addColumn('id', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('version', 'text', (col) => col.notNull())
|
||||
.addColumn('download_status', 'integer')
|
||||
.addColumn('download_progress', 'integer')
|
||||
.addColumn('download_retries', 'integer')
|
||||
.addColumn('download_started_at', 'text')
|
||||
.addColumn('download_completed_at', 'text')
|
||||
.addColumn('upload_status', 'integer')
|
||||
.addColumn('upload_progress', 'integer')
|
||||
.addColumn('upload_retries', 'integer')
|
||||
.addColumn('upload_started_at', 'text')
|
||||
.addColumn('upload_completed_at', 'text')
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema.dropTable('file_states').execute();
|
||||
},
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
export const createMetadataTable: Migration = {
|
||||
up: async (db) => {
|
||||
await db.schema
|
||||
.createTable('metadata')
|
||||
.addColumn('key', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('value', 'text', (col) => col.notNull())
|
||||
.addColumn('created_at', 'text', (col) => col.notNull())
|
||||
.addColumn('updated_at', 'text')
|
||||
.execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema.dropTable('metadata').execute();
|
||||
},
|
||||
};
|
||||
@@ -1,49 +0,0 @@
|
||||
import { Migration } from 'kysely';
|
||||
|
||||
import { CreateUpload } from '@colanode/client/databases/workspace';
|
||||
import { UploadStatus } from '@colanode/client/types/files';
|
||||
|
||||
export const dropFileStatesTable: Migration = {
|
||||
up: async (db) => {
|
||||
const pendingUploads = await db
|
||||
.selectFrom('file_states')
|
||||
.select(['id'])
|
||||
.where('upload_status', '=', 1)
|
||||
.execute();
|
||||
|
||||
if (pendingUploads.length > 0) {
|
||||
const uploadsToCreate: CreateUpload[] = pendingUploads.map((upload) => ({
|
||||
file_id: upload.id,
|
||||
status: UploadStatus.Pending,
|
||||
progress: 0,
|
||||
retries: 0,
|
||||
created_at: new Date().toISOString(),
|
||||
}));
|
||||
|
||||
await db
|
||||
.insertInto('uploads')
|
||||
.values(uploadsToCreate)
|
||||
.onConflict((oc) => oc.column('file_id').doNothing())
|
||||
.execute();
|
||||
}
|
||||
|
||||
await db.schema.dropTable('file_states').execute();
|
||||
},
|
||||
down: async (db) => {
|
||||
await db.schema
|
||||
.createTable('file_states')
|
||||
.addColumn('id', 'text', (col) => col.notNull().primaryKey())
|
||||
.addColumn('version', 'text', (col) => col.notNull())
|
||||
.addColumn('download_status', 'integer')
|
||||
.addColumn('download_progress', 'integer')
|
||||
.addColumn('download_retries', 'integer')
|
||||
.addColumn('download_started_at', 'text')
|
||||
.addColumn('download_completed_at', 'text')
|
||||
.addColumn('upload_status', 'integer')
|
||||
.addColumn('upload_progress', 'integer')
|
||||
.addColumn('upload_retries', 'integer')
|
||||
.addColumn('upload_started_at', 'text')
|
||||
.addColumn('upload_completed_at', 'text')
|
||||
.execute();
|
||||
},
|
||||
};
|
||||
@@ -12,17 +12,14 @@ import { createDocumentStatesTable } from './00009-create-document-states-table'
|
||||
import { createDocumentUpdatesTable } from './00010-create-document-updates-table';
|
||||
import { createDocumentTextsTable } from './00011-create-document-texts-table';
|
||||
import { createCollaborationsTable } from './00012-create-collaborations-table';
|
||||
import { createFileStatesTable } from './00013-create-file-states-table';
|
||||
import { createMutationsTable } from './00014-create-mutations-table';
|
||||
import { createTombstonesTable } from './00015-create-tombstones-table';
|
||||
import { createCursorsTable } from './00016-create-cursors-table';
|
||||
import { createMetadataTable } from './00017-create-metadata-table';
|
||||
import { createNodeReferencesTable } from './00018-create-node-references-table';
|
||||
import { createNodeCountersTable } from './00019-create-node-counters-table';
|
||||
import { createLocalFilesTable } from './00020-create-local-files-table';
|
||||
import { createUploadsTable } from './00021-create-uploads-table';
|
||||
import { createDownloadsTable } from './00022-create-downloads-table';
|
||||
import { dropFileStatesTable } from './00023-drop-file-states-table';
|
||||
import { createMutationsTable } from './00013-create-mutations-table';
|
||||
import { createTombstonesTable } from './00014-create-tombstones-table';
|
||||
import { createCursorsTable } from './00015-create-cursors-table';
|
||||
import { createNodeReferencesTable } from './00016-create-node-references-table';
|
||||
import { createNodeCountersTable } from './00017-create-node-counters-table';
|
||||
import { createLocalFilesTable } from './00018-create-local-files-table';
|
||||
import { createUploadsTable } from './00019-create-uploads-table';
|
||||
import { createDownloadsTable } from './00020-create-downloads-table';
|
||||
|
||||
export const workspaceDatabaseMigrations: Record<string, Migration> = {
|
||||
'00001-create-users-table': createUsersTable,
|
||||
@@ -37,15 +34,12 @@ export const workspaceDatabaseMigrations: Record<string, Migration> = {
|
||||
'00010-create-document-updates-table': createDocumentUpdatesTable,
|
||||
'00011-create-document-texts-table': createDocumentTextsTable,
|
||||
'00012-create-collaborations-table': createCollaborationsTable,
|
||||
'00013-create-file-states-table': createFileStatesTable,
|
||||
'00014-create-mutations-table': createMutationsTable,
|
||||
'00015-create-tombstones-table': createTombstonesTable,
|
||||
'00016-create-cursors-table': createCursorsTable,
|
||||
'00017-create-metadata-table': createMetadataTable,
|
||||
'00018-create-node-references-table': createNodeReferencesTable,
|
||||
'00019-create-node-counters-table': createNodeCountersTable,
|
||||
'00020-create-local-files-table': createLocalFilesTable,
|
||||
'00021-create-uploads-table': createUploadsTable,
|
||||
'00022-create-downloads-table': createDownloadsTable,
|
||||
'00023-drop-file-states-table': dropFileStatesTable,
|
||||
'00013-create-mutations-table': createMutationsTable,
|
||||
'00014-create-tombstones-table': createTombstonesTable,
|
||||
'00015-create-cursors-table': createCursorsTable,
|
||||
'00016-create-node-references-table': createNodeReferencesTable,
|
||||
'00017-create-node-counters-table': createNodeCountersTable,
|
||||
'00018-create-local-files-table': createLocalFilesTable,
|
||||
'00019-create-uploads-table': createUploadsTable,
|
||||
'00020-create-downloads-table': createDownloadsTable,
|
||||
};
|
||||
|
||||
@@ -227,17 +227,6 @@ export type SelectCursor = Selectable<CursorTable>;
|
||||
export type CreateCursor = Insertable<CursorTable>;
|
||||
export type UpdateCursor = Updateable<CursorTable>;
|
||||
|
||||
interface MetadataTable {
|
||||
key: ColumnType<string, string, never>;
|
||||
value: ColumnType<string, string, string>;
|
||||
created_at: ColumnType<string, string, never>;
|
||||
updated_at: ColumnType<string | null, string | null, string | null>;
|
||||
}
|
||||
|
||||
export type SelectWorkspaceMetadata = Selectable<MetadataTable>;
|
||||
export type CreateWorkspaceMetadata = Insertable<MetadataTable>;
|
||||
export type UpdateWorkspaceMetadata = Updateable<MetadataTable>;
|
||||
|
||||
interface LocalFileTable {
|
||||
id: ColumnType<string, string, never>;
|
||||
version: ColumnType<string, string, string>;
|
||||
@@ -314,5 +303,4 @@ export interface WorkspaceDatabaseSchema {
|
||||
mutations: MutationTable;
|
||||
tombstones: TombstoneTable;
|
||||
cursors: CursorTable;
|
||||
metadata: MetadataTable;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapAccountMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
AccountMetadataDeleteMutationInput,
|
||||
AccountMetadataDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/accounts/account-metadata-delete';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
|
||||
export class AccountMetadataDeleteMutationHandler
|
||||
implements MutationHandler<AccountMetadataDeleteMutationInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
constructor(appService: AppService) {
|
||||
this.app = appService;
|
||||
}
|
||||
|
||||
async handleMutation(
|
||||
input: AccountMetadataDeleteMutationInput
|
||||
): Promise<AccountMetadataDeleteMutationOutput> {
|
||||
const account = this.app.getAccount(input.accountId);
|
||||
|
||||
if (!account) {
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
|
||||
const deletedMetadata = await account.database
|
||||
.deleteFrom('metadata')
|
||||
.where('key', '=', input.key)
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!deletedMetadata) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'account.metadata.deleted',
|
||||
accountId: input.accountId,
|
||||
metadata: mapAccountMetadata(deletedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapAccountMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
AccountMetadataUpdateMutationInput,
|
||||
AccountMetadataUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/accounts/account-metadata-update';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
|
||||
export class AccountMetadataUpdateMutationHandler
|
||||
implements MutationHandler<AccountMetadataUpdateMutationInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
constructor(appService: AppService) {
|
||||
this.app = appService;
|
||||
}
|
||||
|
||||
public async handleMutation(
|
||||
input: AccountMetadataUpdateMutationInput
|
||||
): Promise<AccountMetadataUpdateMutationOutput> {
|
||||
const account = this.app.getAccount(input.accountId);
|
||||
|
||||
if (!account) {
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
|
||||
const updatedMetadata = await account.database
|
||||
.insertInto('metadata')
|
||||
.returningAll()
|
||||
.values({
|
||||
key: input.key,
|
||||
value: JSON.stringify(input.value),
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.onConflict((cb) =>
|
||||
cb.columns(['key']).doUpdateSet({
|
||||
value: JSON.stringify(input.value),
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!updatedMetadata) {
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'account.metadata.updated',
|
||||
accountId: input.accountId,
|
||||
metadata: mapAccountMetadata(updatedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -16,63 +16,70 @@ export abstract class AccountMutationHandlerBase {
|
||||
login: LoginSuccessOutput,
|
||||
server: ServerService
|
||||
): Promise<void> {
|
||||
const createdAccount = await this.app.database
|
||||
.insertInto('accounts')
|
||||
.returningAll()
|
||||
.values({
|
||||
id: login.account.id,
|
||||
email: login.account.email,
|
||||
name: login.account.name,
|
||||
server: server.domain,
|
||||
token: login.token,
|
||||
device_id: login.deviceId,
|
||||
avatar: login.account.avatar,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.executeTakeFirst();
|
||||
const { createdAccount, createdWorkspaces } = await this.app.database
|
||||
.transaction()
|
||||
.execute(async (trx) => {
|
||||
const createdAccount = await trx
|
||||
.insertInto('accounts')
|
||||
.returningAll()
|
||||
.values({
|
||||
id: login.account.id,
|
||||
email: login.account.email,
|
||||
name: login.account.name,
|
||||
server: server.domain,
|
||||
token: login.token,
|
||||
device_id: login.deviceId,
|
||||
avatar: login.account.avatar,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!createdAccount) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.AccountLoginFailed,
|
||||
'Account login failed, please try again.'
|
||||
);
|
||||
}
|
||||
if (!createdAccount) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.AccountLoginFailed,
|
||||
'Account login failed, please try again.'
|
||||
);
|
||||
}
|
||||
|
||||
const createdWorkspaces = [];
|
||||
if (login.workspaces.length > 0) {
|
||||
for (const workspace of login.workspaces) {
|
||||
const createdWorkspace = await trx
|
||||
.insertInto('workspaces')
|
||||
.returningAll()
|
||||
.values({
|
||||
workspace_id: workspace.id,
|
||||
name: workspace.name,
|
||||
user_id: workspace.user.id,
|
||||
account_id: createdAccount.id,
|
||||
role: workspace.user.role,
|
||||
storage_limit: workspace.user.storageLimit,
|
||||
max_file_size: workspace.user.maxFileSize,
|
||||
avatar: workspace.avatar,
|
||||
description: workspace.description,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.executeTakeFirst();
|
||||
|
||||
if (createdWorkspace) {
|
||||
createdWorkspaces.push(createdWorkspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { createdAccount, createdWorkspaces };
|
||||
});
|
||||
|
||||
const account = mapAccount(createdAccount);
|
||||
const accountService = await this.app.initAccount(account);
|
||||
await this.app.initAccount(account);
|
||||
|
||||
eventBus.publish({
|
||||
type: 'account.created',
|
||||
account: account,
|
||||
});
|
||||
|
||||
if (login.workspaces.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const workspace of login.workspaces) {
|
||||
const createdWorkspace = await accountService.database
|
||||
.insertInto('workspaces')
|
||||
.returningAll()
|
||||
.values({
|
||||
id: workspace.id,
|
||||
name: workspace.name,
|
||||
user_id: workspace.user.id,
|
||||
account_id: account.id,
|
||||
role: workspace.user.role,
|
||||
storage_limit: workspace.user.storageLimit,
|
||||
max_file_size: workspace.user.maxFileSize,
|
||||
avatar: workspace.avatar,
|
||||
description: workspace.description,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!createdWorkspace) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await accountService.initWorkspace(mapWorkspace(createdWorkspace));
|
||||
for (const createdWorkspace of createdWorkspaces) {
|
||||
await this.app.initWorkspace(createdWorkspace);
|
||||
eventBus.publish({
|
||||
type: 'workspace.created',
|
||||
workspace: mapWorkspace(createdWorkspace),
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapAppMetadata } from '@colanode/client/lib/mappers';
|
||||
import { mapMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
AppMetadataDeleteMutationInput,
|
||||
AppMetadataDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/apps/app-metadata-delete';
|
||||
MetadataDeleteMutationInput,
|
||||
MetadataDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/apps/metadata-delete';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
|
||||
export class AppMetadataDeleteMutationHandler
|
||||
implements MutationHandler<AppMetadataDeleteMutationInput>
|
||||
export class MetadataDeleteMutationHandler
|
||||
implements MutationHandler<MetadataDeleteMutationInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
@@ -17,10 +17,11 @@ export class AppMetadataDeleteMutationHandler
|
||||
}
|
||||
|
||||
async handleMutation(
|
||||
input: AppMetadataDeleteMutationInput
|
||||
): Promise<AppMetadataDeleteMutationOutput> {
|
||||
input: MetadataDeleteMutationInput
|
||||
): Promise<MetadataDeleteMutationOutput> {
|
||||
const deletedMetadata = await this.app.database
|
||||
.deleteFrom('metadata')
|
||||
.where('namespace', '=', input.namespace)
|
||||
.where('key', '=', input.key)
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
@@ -32,8 +33,8 @@ export class AppMetadataDeleteMutationHandler
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'app.metadata.deleted',
|
||||
metadata: mapAppMetadata(deletedMetadata),
|
||||
type: 'metadata.deleted',
|
||||
metadata: mapMetadata(deletedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -1,14 +1,14 @@
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapAppMetadata } from '@colanode/client/lib/mappers';
|
||||
import { mapMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
AppMetadataUpdateMutationInput,
|
||||
AppMetadataUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/apps/app-metadata-update';
|
||||
MetadataUpdateMutationInput,
|
||||
MetadataUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/apps/metadata-update';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
|
||||
export class AppMetadataUpdateMutationHandler
|
||||
implements MutationHandler<AppMetadataUpdateMutationInput>
|
||||
export class MetadataUpdateMutationHandler
|
||||
implements MutationHandler<MetadataUpdateMutationInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
@@ -17,19 +17,20 @@ export class AppMetadataUpdateMutationHandler
|
||||
}
|
||||
|
||||
async handleMutation(
|
||||
input: AppMetadataUpdateMutationInput
|
||||
): Promise<AppMetadataUpdateMutationOutput> {
|
||||
input: MetadataUpdateMutationInput
|
||||
): Promise<MetadataUpdateMutationOutput> {
|
||||
const updatedMetadata = await this.app.database
|
||||
.insertInto('metadata')
|
||||
.returningAll()
|
||||
.values({
|
||||
namespace: input.namespace,
|
||||
key: input.key,
|
||||
value: JSON.stringify(input.value),
|
||||
value: input.value,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.onConflict((cb) =>
|
||||
cb.columns(['key']).doUpdateSet({
|
||||
value: JSON.stringify(input.value),
|
||||
cb.columns(['namespace', 'key']).doUpdateSet({
|
||||
value: input.value,
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
)
|
||||
@@ -42,8 +43,8 @@ export class AppMetadataUpdateMutationHandler
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'app.metadata.updated',
|
||||
metadata: mapAppMetadata(updatedMetadata),
|
||||
type: 'metadata.updated',
|
||||
metadata: mapMetadata(updatedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -54,7 +54,7 @@ export class AvatarUploadMutationHandler
|
||||
.json<AvatarUploadResponse>();
|
||||
|
||||
await this.app.fs.delete(filePath);
|
||||
await account.avatars.downloadAvatar(response.id);
|
||||
await this.app.assets.downloadAvatar(account.id, response.id);
|
||||
|
||||
return {
|
||||
id: response.id,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ChannelCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: ChannelCreateMutationInput
|
||||
): Promise<ChannelCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const space = await workspace.database
|
||||
.selectFrom('nodes')
|
||||
|
||||
@@ -12,7 +12,7 @@ export class ChannelDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: ChannelDeleteMutationInput
|
||||
): Promise<ChannelDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.channelId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ChannelUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: ChannelUpdateMutationInput
|
||||
): Promise<ChannelUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<ChannelAttributes>(
|
||||
input.channelId,
|
||||
|
||||
@@ -19,14 +19,14 @@ export class ChatCreateMutationHandler
|
||||
public async handleMutation(
|
||||
input: ChatCreateMutationInput
|
||||
): Promise<ChatCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const query = sql<ChatRow>`
|
||||
SELECT id
|
||||
FROM nodes
|
||||
WHERE type = 'chat'
|
||||
AND json_extract(attributes, '$.collaborators.${sql.raw(input.collaboratorId)}') is not null
|
||||
AND json_extract(attributes, '$.collaborators.${sql.raw(input.userId)}') is not null
|
||||
AND json_extract(attributes, '$.collaborators.${sql.raw(workspace.userId)}') is not null
|
||||
`.compile(workspace.database);
|
||||
|
||||
const existingChats = await workspace.database.executeQuery(query);
|
||||
@@ -42,7 +42,7 @@ export class ChatCreateMutationHandler
|
||||
type: 'chat',
|
||||
collaborators: {
|
||||
[input.userId]: 'admin',
|
||||
[workspace.userId]: 'admin',
|
||||
[input.collaboratorId]: 'admin',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export class DatabaseCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: DatabaseCreateMutationInput
|
||||
): Promise<DatabaseCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const databaseId = generateId(IdType.Database);
|
||||
const viewId = generateId(IdType.DatabaseView);
|
||||
|
||||
@@ -12,7 +12,7 @@ export class DatabaseDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: DatabaseDeleteMutationInput
|
||||
): Promise<DatabaseDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.databaseId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class DatabaseNameFieldUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: DatabaseNameFieldUpdateMutationInput
|
||||
): Promise<DatabaseNameFieldUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class DatabaseUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: DatabaseUpdateMutationInput
|
||||
): Promise<DatabaseUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
(attributes) => {
|
||||
|
||||
@@ -23,7 +23,7 @@ export class FieldCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: FieldCreateMutationInput
|
||||
): Promise<FieldCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
if (input.fieldType === 'relation') {
|
||||
if (!input.relationDatabaseId) {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class FieldDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: FieldDeleteMutationInput
|
||||
): Promise<FieldDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class FieldNameUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: FieldNameUpdateMutationInput
|
||||
): Promise<FieldNameUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
|
||||
@@ -20,7 +20,7 @@ export class SelectOptionCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: SelectOptionCreateMutationInput
|
||||
): Promise<SelectOptionCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.SelectOption);
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
|
||||
@@ -14,7 +14,7 @@ export class SelectOptionDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: SelectOptionDeleteMutationInput
|
||||
): Promise<SelectOptionDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class SelectOptionUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: SelectOptionUpdateMutationInput
|
||||
): Promise<SelectOptionUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseAttributes>(
|
||||
input.databaseId,
|
||||
|
||||
@@ -19,7 +19,7 @@ export class ViewCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: ViewCreateMutationInput
|
||||
): Promise<ViewCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.DatabaseView);
|
||||
const otherViews = await workspace.database
|
||||
|
||||
@@ -12,7 +12,7 @@ export class ViewDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: ViewDeleteMutationInput
|
||||
): Promise<ViewDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.viewId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ViewNameUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: ViewNameUpdateMutationInput
|
||||
): Promise<ViewNameUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseViewAttributes>(
|
||||
input.viewId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class ViewUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: ViewUpdateMutationInput
|
||||
): Promise<ViewUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<DatabaseViewAttributes>(
|
||||
input.viewId,
|
||||
|
||||
@@ -13,7 +13,7 @@ export class DocumentUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: DocumentUpdateMutationInput
|
||||
): Promise<DocumentUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.documents.updateDocument(
|
||||
input.documentId,
|
||||
decodeState(input.update)
|
||||
|
||||
@@ -13,7 +13,7 @@ export class FileCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: FileCreateMutationInput
|
||||
): Promise<FileCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const fileId = generateId(IdType.File);
|
||||
await workspace.files.createFile(fileId, input.tempFileId, input.parentId);
|
||||
|
||||
@@ -12,7 +12,7 @@ export class FileDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: FileDeleteMutationInput
|
||||
): Promise<FileDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.fileId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class FileDownloadMutationHandler
|
||||
async handleMutation(
|
||||
input: FileDownloadMutationInput
|
||||
): Promise<FileDownloadMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
const path = input.path;
|
||||
|
||||
if (!path) {
|
||||
|
||||
@@ -13,7 +13,7 @@ export class FolderCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: FolderCreateMutationInput
|
||||
): Promise<FolderCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.Folder);
|
||||
const attributes: FolderAttributes = {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class FolderDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: FolderDeleteMutationInput
|
||||
): Promise<FolderDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
await workspace.nodes.deleteNode(input.folderId);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export class FolderUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: FolderUpdateMutationInput
|
||||
): Promise<FolderUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<FolderAttributes>(
|
||||
input.folderId,
|
||||
|
||||
@@ -3,8 +3,6 @@ import { MutationMap } from '@colanode/client/mutations';
|
||||
import { AppService } from '@colanode/client/services';
|
||||
|
||||
import { AccountLogoutMutationHandler } from './accounts/account-logout';
|
||||
import { AccountMetadataDeleteMutationHandler } from './accounts/account-metadata-delete';
|
||||
import { AccountMetadataUpdateMutationHandler } from './accounts/account-metadata-update';
|
||||
import { AccountUpdateMutationHandler } from './accounts/account-update';
|
||||
import { EmailLoginMutationHandler } from './accounts/email-login';
|
||||
import { EmailPasswordResetCompleteMutationHandler } from './accounts/email-password-reset-complete';
|
||||
@@ -12,8 +10,8 @@ import { EmailPasswordResetInitMutationHandler } from './accounts/email-password
|
||||
import { EmailRegisterMutationHandler } from './accounts/email-register';
|
||||
import { EmailVerifyMutationHandler } from './accounts/email-verify';
|
||||
import { GoogleLoginMutationHandler } from './accounts/google-login';
|
||||
import { AppMetadataDeleteMutationHandler } from './apps/app-metadata-delete';
|
||||
import { AppMetadataUpdateMutationHandler } from './apps/app-metadata-update';
|
||||
import { MetadataDeleteMutationHandler } from './apps/metadata-delete';
|
||||
import { MetadataUpdateMutationHandler } from './apps/metadata-update';
|
||||
import { TabCreateMutationHandler } from './apps/tab-create';
|
||||
import { TabDeleteMutationHandler } from './apps/tab-delete';
|
||||
import { TabUpdateMutationHandler } from './apps/tab-update';
|
||||
@@ -73,8 +71,6 @@ import { UserStorageUpdateMutationHandler } from './users/user-storage-update';
|
||||
import { UsersCreateMutationHandler } from './users/users-create';
|
||||
import { WorkspaceCreateMutationHandler } from './workspaces/workspace-create';
|
||||
import { WorkspaceDeleteMutationHandler } from './workspaces/workspace-delete';
|
||||
import { WorkspaceMetadataDeleteMutationHandler } from './workspaces/workspace-metadata-delete';
|
||||
import { WorkspaceMetadataUpdateMutationHandler } from './workspaces/workspace-metadata-update';
|
||||
import { WorkspaceUpdateMutationHandler } from './workspaces/workspace-update';
|
||||
|
||||
export type MutationHandlerMap = {
|
||||
@@ -146,17 +142,9 @@ export const buildMutationHandlerMap = (
|
||||
'page.update': new PageUpdateMutationHandler(app),
|
||||
'folder.update': new FolderUpdateMutationHandler(app),
|
||||
'database.update': new DatabaseUpdateMutationHandler(app),
|
||||
'workspace.metadata.update': new WorkspaceMetadataUpdateMutationHandler(
|
||||
app
|
||||
),
|
||||
'workspace.metadata.delete': new WorkspaceMetadataDeleteMutationHandler(
|
||||
app
|
||||
),
|
||||
'document.update': new DocumentUpdateMutationHandler(app),
|
||||
'app.metadata.update': new AppMetadataUpdateMutationHandler(app),
|
||||
'app.metadata.delete': new AppMetadataDeleteMutationHandler(app),
|
||||
'account.metadata.update': new AccountMetadataUpdateMutationHandler(app),
|
||||
'account.metadata.delete': new AccountMetadataDeleteMutationHandler(app),
|
||||
'metadata.update': new MetadataUpdateMutationHandler(app),
|
||||
'metadata.delete': new MetadataDeleteMutationHandler(app),
|
||||
'email.password.reset.init': new EmailPasswordResetInitMutationHandler(app),
|
||||
'email.password.reset.complete':
|
||||
new EmailPasswordResetCompleteMutationHandler(app),
|
||||
|
||||
@@ -26,7 +26,7 @@ export class MessageCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: MessageCreateMutationInput
|
||||
): Promise<MessageCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const messageId = generateId(IdType.Message);
|
||||
const editorContent = input.content.content ?? [];
|
||||
|
||||
@@ -12,7 +12,7 @@ export class MessageDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: MessageDeleteMutationInput
|
||||
): Promise<MessageDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.messageId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -16,7 +16,7 @@ export class NodeCollaboratorCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeCollaboratorCreateMutationInput
|
||||
): Promise<NodeCollaboratorCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode(
|
||||
input.nodeId,
|
||||
|
||||
@@ -16,7 +16,7 @@ export class NodeCollaboratorDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeCollaboratorDeleteMutationInput
|
||||
): Promise<NodeCollaboratorDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode(
|
||||
input.nodeId,
|
||||
|
||||
@@ -16,7 +16,7 @@ export class NodeCollaboratorUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeCollaboratorUpdateMutationInput
|
||||
): Promise<NodeCollaboratorUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode(
|
||||
input.nodeId,
|
||||
|
||||
@@ -22,7 +22,7 @@ export class NodeInteractionOpenedMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeInteractionOpenedMutationInput
|
||||
): Promise<NodeInteractionOpenedMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const node = await fetchNode(workspace.database, input.nodeId);
|
||||
if (!node) {
|
||||
@@ -123,8 +123,11 @@ export class NodeInteractionOpenedMutationHandler
|
||||
|
||||
eventBus.publish({
|
||||
type: 'node.interaction.updated',
|
||||
accountId: workspace.accountId,
|
||||
workspaceId: workspace.id,
|
||||
workspace: {
|
||||
workspaceId: workspace.workspaceId,
|
||||
userId: workspace.userId,
|
||||
accountId: workspace.accountId,
|
||||
},
|
||||
nodeInteraction: mapNodeInteraction(createdInteraction),
|
||||
});
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ export class NodeInteractionSeenMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeInteractionSeenMutationInput
|
||||
): Promise<NodeInteractionSeenMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const node = await fetchNode(workspace.database, input.nodeId);
|
||||
|
||||
@@ -124,8 +124,11 @@ export class NodeInteractionSeenMutationHandler
|
||||
|
||||
eventBus.publish({
|
||||
type: 'node.interaction.updated',
|
||||
accountId: workspace.accountId,
|
||||
workspaceId: workspace.id,
|
||||
workspace: {
|
||||
workspaceId: workspace.workspaceId,
|
||||
userId: workspace.userId,
|
||||
accountId: workspace.accountId,
|
||||
},
|
||||
nodeInteraction: mapNodeInteraction(createdInteraction),
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export class NodeReactionCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeReactionCreateMutationInput
|
||||
): Promise<NodeReactionCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodeReactions.createNodeReaction(
|
||||
input.nodeId,
|
||||
input.reaction
|
||||
|
||||
@@ -12,7 +12,7 @@ export class NodeReactionDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: NodeReactionDeleteMutationInput
|
||||
): Promise<NodeReactionDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodeReactions.deleteNodeReaction(
|
||||
input.nodeId,
|
||||
input.reaction
|
||||
|
||||
@@ -13,7 +13,7 @@ export class PageCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: PageCreateMutationInput
|
||||
): Promise<PageCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.Page);
|
||||
const attributes: PageAttributes = {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class PageDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: PageDeleteMutationInput
|
||||
): Promise<PageDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.pageId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class PageUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: PageUpdateMutationInput
|
||||
): Promise<PageUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<PageAttributes>(
|
||||
input.pageId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class RecordAvatarUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordAvatarUpdateMutationInput
|
||||
): Promise<RecordAvatarUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<RecordAttributes>(
|
||||
input.recordId,
|
||||
|
||||
@@ -13,7 +13,7 @@ export class RecordCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordCreateMutationInput
|
||||
): Promise<RecordCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const id = generateId(IdType.Record);
|
||||
const attributes: RecordAttributes = {
|
||||
|
||||
@@ -12,7 +12,7 @@ export class RecordDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordDeleteMutationInput
|
||||
): Promise<RecordDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.recordId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class RecordFieldValueDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordFieldValueDeleteMutationInput
|
||||
): Promise<RecordFieldValueDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<RecordAttributes>(
|
||||
input.recordId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class RecordFieldValueSetMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordFieldValueSetMutationInput
|
||||
): Promise<RecordFieldValueSetMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<RecordAttributes>(
|
||||
input.recordId,
|
||||
|
||||
@@ -14,7 +14,7 @@ export class RecordNameUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: RecordNameUpdateMutationInput
|
||||
): Promise<RecordNameUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<RecordAttributes>(
|
||||
input.recordId,
|
||||
|
||||
@@ -26,7 +26,7 @@ export class SpaceChildReorderMutationHandler
|
||||
async handleMutation(
|
||||
input: SpaceChildReorderMutationInput
|
||||
): Promise<SpaceChildReorderMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
const children = await workspace.database
|
||||
.selectFrom('nodes')
|
||||
.where('parent_id', '=', input.spaceId)
|
||||
|
||||
@@ -20,7 +20,7 @@ export class SpaceCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: SpaceCreateMutationInput
|
||||
): Promise<SpaceCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
if (!workspace) {
|
||||
throw new MutationError(
|
||||
|
||||
@@ -12,7 +12,7 @@ export class SpaceDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: SpaceDeleteMutationInput
|
||||
): Promise<SpaceDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
await workspace.nodes.deleteNode(input.spaceId);
|
||||
|
||||
return {
|
||||
|
||||
@@ -14,7 +14,7 @@ export class SpaceUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: SpaceUpdateMutationInput
|
||||
): Promise<SpaceUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
const result = await workspace.nodes.updateNode<SpaceAttributes>(
|
||||
input.spaceId,
|
||||
|
||||
@@ -15,7 +15,7 @@ export class UserRoleUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: UserRoleUpdateMutationInput
|
||||
): Promise<UserRoleUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
try {
|
||||
const body: UserRoleUpdateInput = {
|
||||
@@ -23,9 +23,12 @@ export class UserRoleUpdateMutationHandler
|
||||
};
|
||||
|
||||
const output = await workspace.account.client
|
||||
.patch(`v1/workspaces/${workspace.id}/users/${input.userId}/role`, {
|
||||
json: body,
|
||||
})
|
||||
.patch(
|
||||
`v1/workspaces/${workspace.workspaceId}/users/${input.userId}/role`,
|
||||
{
|
||||
json: body,
|
||||
}
|
||||
)
|
||||
.json<UserOutput>();
|
||||
|
||||
await workspace.users.upsert(output);
|
||||
|
||||
@@ -15,7 +15,7 @@ export class UserStorageUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: UserStorageUpdateMutationInput
|
||||
): Promise<UserStorageUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
try {
|
||||
const body: UserStorageUpdateInput = {
|
||||
@@ -24,9 +24,12 @@ export class UserStorageUpdateMutationHandler
|
||||
};
|
||||
|
||||
const output = await workspace.account.client
|
||||
.patch(`v1/workspaces/${workspace.id}/users/${input.userId}/storage`, {
|
||||
json: body,
|
||||
})
|
||||
.patch(
|
||||
`v1/workspaces/${workspace.workspaceId}/users/${input.userId}/storage`,
|
||||
{
|
||||
json: body,
|
||||
}
|
||||
)
|
||||
.json<UserOutput>();
|
||||
|
||||
await workspace.users.upsert(output);
|
||||
|
||||
@@ -15,7 +15,7 @@ export class UsersCreateMutationHandler
|
||||
async handleMutation(
|
||||
input: UsersCreateMutationInput
|
||||
): Promise<UsersCreateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const workspace = this.getWorkspace(input.userId);
|
||||
|
||||
try {
|
||||
const body: UsersCreateInput = {
|
||||
@@ -23,7 +23,7 @@ export class UsersCreateMutationHandler
|
||||
};
|
||||
|
||||
const output = await workspace.account.client
|
||||
.post(`v1/workspaces/${workspace.id}/users`, {
|
||||
.post(`v1/workspaces/${workspace.workspaceId}/users`, {
|
||||
json: body,
|
||||
})
|
||||
.json<UsersCreateOutput>();
|
||||
|
||||
@@ -9,20 +9,10 @@ export abstract class WorkspaceMutationHandlerBase {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
protected getWorkspace(
|
||||
accountId: string,
|
||||
workspaceId: string
|
||||
): WorkspaceService {
|
||||
const account = this.app.getAccount(accountId);
|
||||
if (!account) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.AccountNotFound,
|
||||
'Account not found or has been logged out already. Try closing the app and opening it again.'
|
||||
);
|
||||
}
|
||||
|
||||
const workspace = account.getWorkspace(workspaceId);
|
||||
protected getWorkspace(userId: string): WorkspaceService {
|
||||
const workspace = this.app.getWorkspace(userId);
|
||||
if (!workspace) {
|
||||
console.log('Workspace not found', userId);
|
||||
throw new MutationError(
|
||||
MutationErrorCode.WorkspaceNotFound,
|
||||
'Workspace not found or has been deleted.'
|
||||
|
||||
@@ -44,11 +44,12 @@ export class WorkspaceCreateMutationHandler
|
||||
})
|
||||
.json<WorkspaceOutput>();
|
||||
|
||||
const createdWorkspace = await account.database
|
||||
const createdWorkspace = await this.app.database
|
||||
.insertInto('workspaces')
|
||||
.returningAll()
|
||||
.values({
|
||||
id: response.id,
|
||||
user_id: response.user.id,
|
||||
workspace_id: response.id,
|
||||
account_id: response.user.accountId,
|
||||
name: response.name,
|
||||
description: response.description,
|
||||
@@ -56,7 +57,6 @@ export class WorkspaceCreateMutationHandler
|
||||
role: response.user.role,
|
||||
storage_limit: response.user.storageLimit,
|
||||
max_file_size: response.user.maxFileSize,
|
||||
user_id: response.user.id,
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.onConflict((cb) => cb.doNothing())
|
||||
@@ -69,16 +69,16 @@ export class WorkspaceCreateMutationHandler
|
||||
);
|
||||
}
|
||||
|
||||
const workspace = mapWorkspace(createdWorkspace);
|
||||
await account.initWorkspace(workspace);
|
||||
await this.app.initWorkspace(createdWorkspace);
|
||||
|
||||
const workspace = mapWorkspace(createdWorkspace);
|
||||
eventBus.publish({
|
||||
type: 'workspace.created',
|
||||
workspace: workspace,
|
||||
});
|
||||
|
||||
return {
|
||||
id: createdWorkspace.id,
|
||||
id: createdWorkspace.workspace_id,
|
||||
userId: createdWorkspace.user_id,
|
||||
};
|
||||
} catch (error) {
|
||||
|
||||
@@ -20,16 +20,7 @@ export class WorkspaceDeleteMutationHandler
|
||||
async handleMutation(
|
||||
input: WorkspaceDeleteMutationInput
|
||||
): Promise<WorkspaceDeleteMutationOutput> {
|
||||
const accountService = this.app.getAccount(input.accountId);
|
||||
|
||||
if (!accountService) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.AccountNotFound,
|
||||
'Account not found or has been logged out.'
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceService = accountService.getWorkspace(input.workspaceId);
|
||||
const workspaceService = this.app.getWorkspace(input.userId);
|
||||
if (!workspaceService) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.WorkspaceNotFound,
|
||||
@@ -37,12 +28,20 @@ export class WorkspaceDeleteMutationHandler
|
||||
);
|
||||
}
|
||||
|
||||
const accountService = this.app.getAccount(workspaceService.accountId);
|
||||
if (!accountService) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.AccountNotFound,
|
||||
'Account not found or has been logged out.'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await accountService.client
|
||||
.delete(`v1/workspaces/${input.workspaceId}`)
|
||||
.delete(`v1/workspaces/${workspaceService.workspaceId}`)
|
||||
.json<WorkspaceOutput>();
|
||||
|
||||
await accountService.deleteWorkspace(response.id);
|
||||
await workspaceService.delete();
|
||||
|
||||
return {
|
||||
id: response.id,
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapWorkspaceMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
WorkspaceMetadataDeleteMutationInput,
|
||||
WorkspaceMetadataDeleteMutationOutput,
|
||||
} from '@colanode/client/mutations/workspaces/workspace-metadata-delete';
|
||||
|
||||
export class WorkspaceMetadataDeleteMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<WorkspaceMetadataDeleteMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: WorkspaceMetadataDeleteMutationInput
|
||||
): Promise<WorkspaceMetadataDeleteMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
const deletedMetadata = await workspace.database
|
||||
.deleteFrom('metadata')
|
||||
.where('key', '=', input.key)
|
||||
.returningAll()
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!deletedMetadata) {
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'workspace.metadata.deleted',
|
||||
accountId: input.accountId,
|
||||
workspaceId: input.workspaceId,
|
||||
metadata: mapWorkspaceMetadata(deletedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import { WorkspaceMutationHandlerBase } from '@colanode/client/handlers/mutations/workspace-mutation-handler-base';
|
||||
import { eventBus } from '@colanode/client/lib/event-bus';
|
||||
import { mapWorkspaceMetadata } from '@colanode/client/lib/mappers';
|
||||
import { MutationHandler } from '@colanode/client/lib/types';
|
||||
import {
|
||||
WorkspaceMetadataUpdateMutationInput,
|
||||
WorkspaceMetadataUpdateMutationOutput,
|
||||
} from '@colanode/client/mutations/workspaces/workspace-metadata-update';
|
||||
|
||||
export class WorkspaceMetadataUpdateMutationHandler
|
||||
extends WorkspaceMutationHandlerBase
|
||||
implements MutationHandler<WorkspaceMetadataUpdateMutationInput>
|
||||
{
|
||||
async handleMutation(
|
||||
input: WorkspaceMetadataUpdateMutationInput
|
||||
): Promise<WorkspaceMetadataUpdateMutationOutput> {
|
||||
const workspace = this.getWorkspace(input.accountId, input.workspaceId);
|
||||
|
||||
const updatedMetadata = await workspace.database
|
||||
.insertInto('metadata')
|
||||
.returningAll()
|
||||
.values({
|
||||
key: input.key,
|
||||
value: JSON.stringify(input.value),
|
||||
created_at: new Date().toISOString(),
|
||||
})
|
||||
.onConflict((cb) =>
|
||||
cb.columns(['key']).doUpdateSet({
|
||||
value: JSON.stringify(input.value),
|
||||
updated_at: new Date().toISOString(),
|
||||
})
|
||||
)
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!updatedMetadata) {
|
||||
return {
|
||||
success: false,
|
||||
};
|
||||
}
|
||||
|
||||
eventBus.publish({
|
||||
type: 'workspace.metadata.updated',
|
||||
accountId: input.accountId,
|
||||
workspaceId: input.workspaceId,
|
||||
metadata: mapWorkspaceMetadata(updatedMetadata),
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export class WorkspaceUpdateMutationHandler
|
||||
async handleMutation(
|
||||
input: WorkspaceUpdateMutationInput
|
||||
): Promise<WorkspaceUpdateMutationOutput> {
|
||||
const accountService = this.app.getAccount(input.accountId);
|
||||
const accountService = this.app.getAccount(input.userId);
|
||||
|
||||
if (!accountService) {
|
||||
throw new MutationError(
|
||||
@@ -33,7 +33,7 @@ export class WorkspaceUpdateMutationHandler
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceService = accountService.getWorkspace(input.id);
|
||||
const workspaceService = this.app.getWorkspace(input.userId);
|
||||
if (!workspaceService) {
|
||||
throw new MutationError(
|
||||
MutationErrorCode.WorkspaceNotFound,
|
||||
@@ -54,7 +54,7 @@ export class WorkspaceUpdateMutationHandler
|
||||
})
|
||||
.json<Workspace>();
|
||||
|
||||
const updatedWorkspace = await accountService.database
|
||||
const updatedWorkspace = await this.app.database
|
||||
.updateTable('workspaces')
|
||||
.returningAll()
|
||||
.set({
|
||||
@@ -63,7 +63,7 @@ export class WorkspaceUpdateMutationHandler
|
||||
avatar: response.avatar,
|
||||
role: response.role,
|
||||
})
|
||||
.where((eb) => eb.and([eb('id', '=', input.id)]))
|
||||
.where((eb) => eb.and([eb('user_id', '=', input.userId)]))
|
||||
.executeTakeFirst();
|
||||
|
||||
if (!updatedWorkspace) {
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
import { SelectAccountMetadata } from '@colanode/client/databases/account/schema';
|
||||
import { mapAccountMetadata } from '@colanode/client/lib/mappers';
|
||||
import { ChangeCheckResult, QueryHandler } from '@colanode/client/lib/types';
|
||||
import { AccountMetadataListQueryInput } from '@colanode/client/queries/accounts/account-metadata-list';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
import { AccountMetadata } from '@colanode/client/types/accounts';
|
||||
import { Event } from '@colanode/client/types/events';
|
||||
|
||||
export class AccountMetadataListQueryHandler
|
||||
implements QueryHandler<AccountMetadataListQueryInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
constructor(app: AppService) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public async handleQuery(
|
||||
input: AccountMetadataListQueryInput
|
||||
): Promise<AccountMetadata[]> {
|
||||
const rows = await this.getAccountMetadata(input.accountId);
|
||||
if (!rows) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return rows.map(mapAccountMetadata);
|
||||
}
|
||||
|
||||
public async checkForChanges(
|
||||
event: Event,
|
||||
input: AccountMetadataListQueryInput,
|
||||
output: AccountMetadata[]
|
||||
): Promise<ChangeCheckResult<AccountMetadataListQueryInput>> {
|
||||
if (
|
||||
event.type === 'account.created' &&
|
||||
event.account.id === input.accountId
|
||||
) {
|
||||
const result = await this.handleQuery(input);
|
||||
return {
|
||||
hasChanges: true,
|
||||
result,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
event.type === 'account.deleted' &&
|
||||
event.account.id === input.accountId
|
||||
) {
|
||||
return {
|
||||
hasChanges: true,
|
||||
result: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
event.type === 'account.metadata.updated' &&
|
||||
event.accountId === input.accountId
|
||||
) {
|
||||
const newOutput = [
|
||||
...output.filter((metadata) => metadata.key !== event.metadata.key),
|
||||
event.metadata,
|
||||
];
|
||||
|
||||
return {
|
||||
hasChanges: true,
|
||||
result: newOutput,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
event.type === 'account.metadata.deleted' &&
|
||||
event.accountId === input.accountId
|
||||
) {
|
||||
const newOutput = output.filter(
|
||||
(metadata) => metadata.key !== event.metadata.key
|
||||
);
|
||||
|
||||
return {
|
||||
hasChanges: true,
|
||||
result: newOutput,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
hasChanges: false,
|
||||
};
|
||||
}
|
||||
|
||||
private async getAccountMetadata(
|
||||
accountId: string
|
||||
): Promise<SelectAccountMetadata[] | undefined> {
|
||||
const account = this.app.getAccount(accountId);
|
||||
|
||||
if (!account) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const rows = await account.database
|
||||
.selectFrom('metadata')
|
||||
.selectAll()
|
||||
.execute();
|
||||
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import { SelectAppMetadata } from '@colanode/client/databases/app/schema';
|
||||
import { mapAppMetadata } from '@colanode/client/lib/mappers';
|
||||
import { SelectMetadata } from '@colanode/client/databases/app/schema';
|
||||
import { mapMetadata } from '@colanode/client/lib/mappers';
|
||||
import { ChangeCheckResult, QueryHandler } from '@colanode/client/lib/types';
|
||||
import { AppMetadataListQueryInput } from '@colanode/client/queries/apps/app-metadata-list';
|
||||
import { MetadataListQueryInput } from '@colanode/client/queries/apps/metadata-list';
|
||||
import { AppService } from '@colanode/client/services/app-service';
|
||||
import { AppMetadata } from '@colanode/client/types/apps';
|
||||
import { Metadata } from '@colanode/client/types/apps';
|
||||
import { Event } from '@colanode/client/types/events';
|
||||
|
||||
export class AppMetadataListQueryHandler
|
||||
implements QueryHandler<AppMetadataListQueryInput>
|
||||
export class MetadataListQueryHandler
|
||||
implements QueryHandler<MetadataListQueryInput>
|
||||
{
|
||||
private readonly app: AppService;
|
||||
|
||||
@@ -15,23 +15,21 @@ export class AppMetadataListQueryHandler
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public async handleQuery(
|
||||
_: AppMetadataListQueryInput
|
||||
): Promise<AppMetadata[]> {
|
||||
public async handleQuery(_: MetadataListQueryInput): Promise<Metadata[]> {
|
||||
const rows = await this.getAppMetadata();
|
||||
if (!rows) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return rows.map(mapAppMetadata);
|
||||
return rows.map(mapMetadata);
|
||||
}
|
||||
|
||||
public async checkForChanges(
|
||||
event: Event,
|
||||
_: AppMetadataListQueryInput,
|
||||
output: AppMetadata[]
|
||||
): Promise<ChangeCheckResult<AppMetadataListQueryInput>> {
|
||||
if (event.type === 'app.metadata.updated') {
|
||||
_: MetadataListQueryInput,
|
||||
output: Metadata[]
|
||||
): Promise<ChangeCheckResult<MetadataListQueryInput>> {
|
||||
if (event.type === 'metadata.updated') {
|
||||
const newOutput = [
|
||||
...output.filter((metadata) => metadata.key !== event.metadata.key),
|
||||
event.metadata,
|
||||
@@ -43,7 +41,7 @@ export class AppMetadataListQueryHandler
|
||||
};
|
||||
}
|
||||
|
||||
if (event.type === 'app.metadata.deleted') {
|
||||
if (event.type === 'metadata.deleted') {
|
||||
const newOutput = output.filter(
|
||||
(metadata) => metadata.key !== event.metadata.key
|
||||
);
|
||||
@@ -59,7 +57,7 @@ export class AppMetadataListQueryHandler
|
||||
};
|
||||
}
|
||||
|
||||
private async getAppMetadata(): Promise<SelectAppMetadata[] | undefined> {
|
||||
private async getAppMetadata(): Promise<SelectMetadata[] | undefined> {
|
||||
const rows = await this.app.database
|
||||
.selectFrom('metadata')
|
||||
.selectAll()
|
||||
@@ -19,29 +19,21 @@ export class AvatarGetQueryHandler
|
||||
return null;
|
||||
}
|
||||
|
||||
return account.avatars.getAvatar(input.avatarId, true);
|
||||
return this.app.assets.getAvatar(account.id, input.avatarId, true);
|
||||
}
|
||||
|
||||
public async checkForChanges(
|
||||
event: Event,
|
||||
input: AvatarGetQueryInput
|
||||
): Promise<ChangeCheckResult<AvatarGetQueryInput>> {
|
||||
if (
|
||||
event.type === 'avatar.created' &&
|
||||
event.accountId === input.accountId &&
|
||||
event.avatar.id === input.avatarId
|
||||
) {
|
||||
if (event.type === 'avatar.created' && event.avatar.id === input.avatarId) {
|
||||
return {
|
||||
hasChanges: true,
|
||||
result: event.avatar,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
event.type === 'avatar.deleted' &&
|
||||
event.accountId === input.accountId &&
|
||||
event.avatar.id === input.avatarId
|
||||
) {
|
||||
if (event.type === 'avatar.deleted' && event.avatar.id === input.avatarId) {
|
||||
return {
|
||||
hasChanges: true,
|
||||
result: null,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user