Add a core package to be reused by desktop and server

This commit is contained in:
Hakan Shehu
2024-11-07 09:15:00 +01:00
parent 00f6ac971e
commit 8a5409ad29
277 changed files with 1193 additions and 1089 deletions

View File

@@ -4,6 +4,6 @@ module.exports = {
'plugin:react/recommended', 'plugin:react/recommended',
'plugin:react/jsx-runtime', 'plugin:react/jsx-runtime',
'@electron-toolkit/eslint-config-ts/recommended', '@electron-toolkit/eslint-config-ts/recommended',
'@electron-toolkit/eslint-config-prettier' '@electron-toolkit/eslint-config-prettier',
] ],
} };

View File

@@ -4,7 +4,11 @@ import react from '@vitejs/plugin-react';
export default defineConfig({ export default defineConfig({
main: { main: {
plugins: [externalizeDepsPlugin()], plugins: [
externalizeDepsPlugin({
exclude: ['@colanode/core'],
}),
],
resolve: { resolve: {
alias: { alias: {
'@/main': resolve('src/main'), '@/main': resolve('src/main'),

View File

@@ -20,9 +20,9 @@
"build:linux": "electron-vite build && electron-builder --linux" "build:linux": "electron-vite build && electron-builder --linux"
}, },
"dependencies": { "dependencies": {
"@colanode/core": "workspace:*",
"@electron-toolkit/preload": "^3.0.1", "@electron-toolkit/preload": "^3.0.1",
"@electron-toolkit/utils": "^3.0.0", "@electron-toolkit/utils": "^3.0.0",
"electron-updater": "^6.1.7",
"@hookform/resolvers": "^3.9.0", "@hookform/resolvers": "^3.9.0",
"@radix-ui/react-alert-dialog": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.1.2",
"@radix-ui/react-checkbox": "^1.1.2", "@radix-ui/react-checkbox": "^1.1.2",
@@ -78,7 +78,7 @@
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "^1.0.0", "cmdk": "^1.0.0",
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"diff": "^7.0.0", "electron-updater": "^6.1.7",
"form-data": "^4.0.1", "form-data": "^4.0.1",
"fractional-indexing-jittered": "^0.9.1", "fractional-indexing-jittered": "^0.9.1",
"is-hotkey": "^0.2.0", "is-hotkey": "^0.2.0",
@@ -104,27 +104,9 @@
"tailwindcss-animate": "^1.0.7", "tailwindcss-animate": "^1.0.7",
"ts-pattern": "^5.5.0", "ts-pattern": "^5.5.0",
"ulid": "^2.3.0", "ulid": "^2.3.0",
"ws": "^8.18.0", "ws": "^8.18.0"
"yjs": "^13.6.20",
"zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
"@electron-toolkit/eslint-config-ts": "^2.0.0",
"@electron-toolkit/tsconfig": "^1.0.1",
"@types/node": "^20.14.8",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"electron": "^31.0.2",
"electron-builder": "^24.13.3",
"electron-vite": "^2.3.0",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.34.3",
"prettier": "^3.3.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"vite": "^5.3.1",
"@electron-forge/cli": "^7.5.0", "@electron-forge/cli": "^7.5.0",
"@electron-forge/maker-deb": "^7.5.0", "@electron-forge/maker-deb": "^7.5.0",
"@electron-forge/maker-rpm": "^7.5.0", "@electron-forge/maker-rpm": "^7.5.0",
@@ -133,22 +115,38 @@
"@electron-forge/plugin-auto-unpack-natives": "^7.5.0", "@electron-forge/plugin-auto-unpack-natives": "^7.5.0",
"@electron-forge/plugin-fuses": "^7.5.0", "@electron-forge/plugin-fuses": "^7.5.0",
"@electron-forge/plugin-vite": "^7.5.0", "@electron-forge/plugin-vite": "^7.5.0",
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
"@electron-toolkit/eslint-config-ts": "^2.0.0",
"@electron-toolkit/tsconfig": "^1.0.1",
"@electron/fuses": "^1.8.0", "@electron/fuses": "^1.8.0",
"@types/better-sqlite3": "^7.6.11", "@types/better-sqlite3": "^7.6.11",
"@types/diff": "^5.2.3", "@types/diff": "^5.2.3",
"@types/is-hotkey": "^0.1.10", "@types/is-hotkey": "^0.1.10",
"@types/lodash": "^4.17.12", "@types/lodash": "^4.17.12",
"@types/mime-types": "^2.1.4", "@types/mime-types": "^2.1.4",
"@types/node": "^20.14.8",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/react-window": "^1.8.8", "@types/react-window": "^1.8.8",
"@types/ws": "^8.5.12", "@types/ws": "^8.5.12",
"@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0", "@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"electron": "^31.0.2",
"electron-builder": "^24.13.3",
"electron-vite": "^2.3.0",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-react": "^7.34.3",
"node-abi": "^3.71.0", "node-abi": "^3.71.0",
"postcss": "^8.4.47", "postcss": "^8.4.47",
"prettier": "^3.3.2",
"prettier-plugin-tailwindcss": "^0.6.8", "prettier-plugin-tailwindcss": "^0.6.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.14", "tailwindcss": "^3.4.14",
"ts-node": "^10.9.2" "ts-node": "^10.9.2",
"vite": "^5.3.1"
} }
} }

View File

@@ -5,7 +5,7 @@ import {
ViewFilterAttributes, ViewFilterAttributes,
ViewFieldAttributes, ViewFieldAttributes,
RecordNode, RecordNode,
} from '@/registry'; } from '@colanode/core';
import { compareString, isStringArray } from '@/lib/utils'; import { compareString, isStringArray } from '@/lib/utils';
import { generateNodeIndex } from './nodes'; import { generateNodeIndex } from './nodes';
@@ -576,9 +576,9 @@ const recordMatchesBooleanFilter = (
}; };
const recordMatchesCollaboratorFilter = ( const recordMatchesCollaboratorFilter = (
record: RecordNode, _: RecordNode,
filter: ViewFieldFilterAttributes, __: ViewFieldFilterAttributes,
field: FieldAttributes ___: FieldAttributes
) => { ) => {
return false; return false;
}; };
@@ -739,9 +739,9 @@ const recordMatchesEmailFilter = (
}; };
const recordMatchesFileFilter = ( const recordMatchesFileFilter = (
record: RecordNode, _: RecordNode,
filter: ViewFieldFilterAttributes, __: ViewFieldFilterAttributes,
field: FieldAttributes ___: FieldAttributes
) => { ) => {
return false; return false;
}; };

View File

@@ -3,7 +3,7 @@ import { generateId, getIdTypeFromNode } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { JSONContent } from '@tiptap/core'; import { JSONContent } from '@tiptap/core';
import { Block, BlockLeaf } from '@/registry'; import { Block, BlockLeaf } from '@colanode/core';
const leafBlockTypes = new Set([ const leafBlockTypes = new Set([
EditorNodeTypes.Paragraph, EditorNodeTypes.Paragraph,
@@ -17,7 +17,7 @@ const leafBlockTypes = new Set([
export const mapContentsToBlocks = ( export const mapContentsToBlocks = (
parentId: string, parentId: string,
contents: JSONContent[], contents: JSONContent[],
blocksMap: Map<string, Block>, blocksMap: Map<string, Block>
): Block[] => { ): Block[] => {
const blocks: Block[] = []; const blocks: Block[] = [];
mapAndPushContentsToBlocks(contents, parentId, blocks, blocksMap); mapAndPushContentsToBlocks(contents, parentId, blocks, blocksMap);
@@ -29,7 +29,7 @@ const mapAndPushContentsToBlocks = (
contents: JSONContent[] | null | undefined, contents: JSONContent[] | null | undefined,
parentId: string, parentId: string,
blocks: Block[], blocks: Block[],
blocksMap: Map<string, Block>, blocksMap: Map<string, Block>
): void => { ): void => {
if (!contents) { if (!contents) {
return; return;
@@ -43,7 +43,7 @@ const mapAndPushContentToBlock = (
content: JSONContent, content: JSONContent,
parentId: string, parentId: string,
blocks: Block[], blocks: Block[],
blocksMap: Map<string, Block>, blocksMap: Map<string, Block>
): void => { ): void => {
if (!content.type) { if (!content.type) {
throw new Error('Invalid content type'); throw new Error('Invalid content type');
@@ -77,7 +77,7 @@ const mapAndPushContentToBlock = (
const mapContentsToBlockLeafs = ( const mapContentsToBlockLeafs = (
type: string, type: string,
contents?: JSONContent[], contents?: JSONContent[]
): BlockLeaf[] | null => { ): BlockLeaf[] | null => {
if (!leafBlockTypes.has(type) || contents == null || contents.length === 0) { if (!leafBlockTypes.has(type) || contents == null || contents.length === 0) {
return null; return null;
@@ -106,7 +106,7 @@ const mapContentsToBlockLeafs = (
export const mapBlocksToContents = ( export const mapBlocksToContents = (
parentId: string, parentId: string,
blocks: Block[], blocks: Block[]
): JSONContent[] => { ): JSONContent[] => {
const contents: JSONContent[] = []; const contents: JSONContent[] = [];
const children = blocks const children = blocks
@@ -134,7 +134,7 @@ const mapBlockToContent = (block: Block, blocks: Block[]): JSONContent => {
}; };
const mapBlockLeafsToContents = ( const mapBlockLeafsToContents = (
leafs: BlockLeaf[] | null, leafs: BlockLeaf[] | null
): JSONContent[] | undefined => { ): JSONContent[] | undefined => {
if (leafs == null) { if (leafs == null) {
return undefined; return undefined;

View File

@@ -1,11 +1,9 @@
import { SelectNode } from '@/main/data/workspace/schema';
import { Node } from '@/registry';
import { generateKeyBetween } from 'fractional-indexing-jittered'; import { generateKeyBetween } from 'fractional-indexing-jittered';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
export const generateNodeIndex = ( export const generateNodeIndex = (
previous?: string | null, previous?: string | null,
next?: string | null, next?: string | null
) => { ) => {
const lower = previous === undefined ? null : previous; const lower = previous === undefined ? null : previous;
const upper = next === undefined ? null : next; const upper = next === undefined ? null : next;
@@ -13,24 +11,6 @@ export const generateNodeIndex = (
return generateKeyBetween(lower, upper); return generateKeyBetween(lower, upper);
}; };
export const mapNode = (row: SelectNode): Node => {
return {
id: row.id,
type: row.type as any,
index: row.index,
parentId: row.parent_id,
attributes: JSON.parse(row.attributes),
createdAt: row.created_at,
createdBy: row.created_by,
updatedAt: row.updated_at,
updatedBy: row.updated_by,
versionId: row.version_id,
serverCreatedAt: row.server_created_at,
serverUpdatedAt: row.server_updated_at,
serverVersionId: row.server_version_id,
};
};
export const getDefaultNodeIcon = (type: string) => { export const getDefaultNodeIcon = (type: string) => {
switch (type) { switch (type) {
case NodeTypes.Channel: case NodeTypes.Channel:

View File

@@ -1,8 +0,0 @@
import { SelectServer } from '@/main/data/app/schema';
import { ServerAttributes } from '@/types/servers';
export const buildSynapseUrl = (server: SelectServer, deviceId: string) => {
const attributes = JSON.parse(server.attributes) as ServerAttributes;
const protocol = attributes?.insecure ? 'ws' : 'wss';
return `${protocol}://${server.domain}/v1/synapse?device_id=${deviceId}`;
};

View File

@@ -13,7 +13,7 @@ import { databaseManager } from './data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { mediator } from '@/main/mediator'; import { mediator } from '@/main/mediator';
import { getWorkspaceFilesDirectoryPath } from '@/main/utils'; import { getWorkspaceFilesDirectoryPath } from '@/main/utils';
import { FileAttributes } from '@/registry'; import { FileAttributes } from '@colanode/core';
class FileManager { class FileManager {
public async handleFileRequest(request: Request): Promise<Response> { public async handleFileRequest(request: Request): Promise<Response> {
@@ -39,7 +39,7 @@ class FileManager {
filePath: string, filePath: string,
fileId: string, fileId: string,
fileExtension: string, fileExtension: string,
userId: string, userId: string
): void { ): void {
const filesDir = getWorkspaceFilesDirectoryPath(userId); const filesDir = getWorkspaceFilesDirectoryPath(userId);
@@ -49,7 +49,7 @@ class FileManager {
const destinationFilePath = path.join( const destinationFilePath = path.join(
filesDir, filesDir,
`${fileId}${fileExtension}`, `${fileId}${fileExtension}`
); );
fs.copyFileSync(filePath, destinationFilePath); fs.copyFileSync(filePath, destinationFilePath);
} }
@@ -88,10 +88,10 @@ class FileManager {
} }
public async checkForUploads( public async checkForUploads(
credentials: WorkspaceCredentials, credentials: WorkspaceCredentials
): Promise<void> { ): Promise<void> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
credentials.userId, credentials.userId
); );
const uploads = await workspaceDatabase const uploads = await workspaceDatabase
@@ -133,7 +133,7 @@ class FileManager {
const attributes: FileAttributes = JSON.parse(file.attributes); const attributes: FileAttributes = JSON.parse(file.attributes);
const filePath = path.join( const filePath = path.join(
filesDir, filesDir,
`${upload.node_id}${attributes.extension}`, `${upload.node_id}${attributes.extension}`
); );
if (!fs.existsSync(filePath)) { if (!fs.existsSync(filePath)) {
@@ -153,7 +153,7 @@ class FileManager {
serverDomain: credentials.serverDomain, serverDomain: credentials.serverDomain,
serverAttributes: credentials.serverAttributes, serverAttributes: credentials.serverAttributes,
token: credentials.token, token: credentials.token,
}, }
); );
const presignedUrl = data.url; const presignedUrl = data.url;
@@ -189,10 +189,10 @@ class FileManager {
} }
public async checkForDownloads( public async checkForDownloads(
credentials: WorkspaceCredentials, credentials: WorkspaceCredentials
): Promise<void> { ): Promise<void> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
credentials.userId, credentials.userId
); );
const downloads = await workspaceDatabase const downloads = await workspaceDatabase
@@ -229,7 +229,7 @@ class FileManager {
const attributes: FileAttributes = JSON.parse(file.attributes); const attributes: FileAttributes = JSON.parse(file.attributes);
const filePath = path.join( const filePath = path.join(
filesDir, filesDir,
`${download.node_id}${attributes.extension}`, `${download.node_id}${attributes.extension}`
); );
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
@@ -251,7 +251,7 @@ class FileManager {
serverDomain: credentials.serverDomain, serverDomain: credentials.serverDomain,
serverAttributes: credentials.serverAttributes, serverAttributes: credentials.serverAttributes,
token: credentials.token, token: credentials.token,
}, }
); );
const presignedUrl = data.url; const presignedUrl = data.url;

View File

@@ -1,6 +1,6 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { AccountUpdateOutput } from '@/types/accounts'; import { AccountUpdateOutput } from '@/types/accounts';
import { AccountUpdateMutationInput } from '@/operations/mutations/account-update'; import { AccountUpdateMutationInput } from '@/operations/mutations/account-update';
@@ -8,7 +8,7 @@ export class AccountUpdateMutationHandler
implements MutationHandler<AccountUpdateMutationInput> implements MutationHandler<AccountUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: AccountUpdateMutationInput, input: AccountUpdateMutationInput
): Promise<MutationResult<AccountUpdateMutationInput>> { ): Promise<MutationResult<AccountUpdateMutationInput>> {
const account = await databaseManager.appDatabase const account = await databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')
@@ -40,7 +40,7 @@ export class AccountUpdateMutationHandler
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
token: account.token, token: account.token,
}, }
); );
await databaseManager.appDatabase await databaseManager.appDatabase

View File

@@ -1,7 +1,7 @@
import fs from 'fs'; import fs from 'fs';
import FormData from 'form-data'; import FormData from 'form-data';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { AvatarUploadMutationInput } from '@/operations/mutations/avatar-upload'; import { AvatarUploadMutationInput } from '@/operations/mutations/avatar-upload';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
@@ -13,7 +13,7 @@ export class AvatarUploadMutationHandler
implements MutationHandler<AvatarUploadMutationInput> implements MutationHandler<AvatarUploadMutationInput>
{ {
async handleMutation( async handleMutation(
input: AvatarUploadMutationInput, input: AvatarUploadMutationInput
): Promise<MutationResult<AvatarUploadMutationInput>> { ): Promise<MutationResult<AvatarUploadMutationInput>> {
const credentials = await databaseManager.appDatabase const credentials = await databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')
@@ -45,7 +45,7 @@ export class AvatarUploadMutationHandler
serverAttributes: credentials.attributes, serverAttributes: credentials.attributes,
token: credentials.token, token: credentials.token,
headers: formData.getHeaders(), headers: formData.getHeaders(),
}, }
); );
return { return {

View File

@@ -1,19 +1,19 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ChannelCreateMutationInput } from '@/operations/mutations/channel-create'; import { ChannelCreateMutationInput } from '@/operations/mutations/channel-create';
import { ChannelAttributes } from '@/registry'; import { ChannelAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class ChannelCreateMutationHandler export class ChannelCreateMutationHandler
implements MutationHandler<ChannelCreateMutationInput> implements MutationHandler<ChannelCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: ChannelCreateMutationInput, input: ChannelCreateMutationInput
): Promise<MutationResult<ChannelCreateMutationInput>> { ): Promise<MutationResult<ChannelCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const maxIndexResult = await workspaceDatabase const maxIndexResult = await workspaceDatabase

View File

@@ -1,10 +1,10 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { NodeRole, NodeTypes } from '@/lib/constants'; import { NodeRole, NodeTypes } from '@/lib/constants';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ChatCreateMutationInput } from '@/operations/mutations/chat-create'; import { ChatCreateMutationInput } from '@/operations/mutations/chat-create';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { ChatAttributes } from '@/registry'; import { ChatAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
interface ChatRow { interface ChatRow {
@@ -15,10 +15,10 @@ export class ChatCreateMutationHandler
implements MutationHandler<ChatCreateMutationInput> implements MutationHandler<ChatCreateMutationInput>
{ {
public async handleMutation( public async handleMutation(
input: ChatCreateMutationInput, input: ChatCreateMutationInput
): Promise<MutationResult<ChatCreateMutationInput>> { ): Promise<MutationResult<ChatCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const query = sql<ChatRow>` const query = sql<ChatRow>`

View File

@@ -1,8 +1,8 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { DatabaseCreateMutationInput } from '@/operations/mutations/database-create'; import { DatabaseCreateMutationInput } from '@/operations/mutations/database-create';
import { DatabaseAttributes } from '@/registry'; import { DatabaseAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
@@ -10,10 +10,10 @@ export class DatabaseCreateMutationHandler
implements MutationHandler<DatabaseCreateMutationInput> implements MutationHandler<DatabaseCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: DatabaseCreateMutationInput, input: DatabaseCreateMutationInput
): Promise<MutationResult<DatabaseCreateMutationInput>> { ): Promise<MutationResult<DatabaseCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const databaseId = generateId(IdType.Database); const databaseId = generateId(IdType.Database);

View File

@@ -1,14 +1,14 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { DocumentSaveMutationInput } from '@/operations/mutations/document-save'; import { DocumentSaveMutationInput } from '@/operations/mutations/document-save';
import { mapContentsToBlocks } from '@/lib/editor'; import { mapContentsToBlocks } from '@/lib/editor';
import { Block } from '@/registry'; import { Block } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class DocumentSaveMutationHandler export class DocumentSaveMutationHandler
implements MutationHandler<DocumentSaveMutationInput> implements MutationHandler<DocumentSaveMutationInput>
{ {
async handleMutation( async handleMutation(
input: DocumentSaveMutationInput, input: DocumentSaveMutationInput
): Promise<MutationResult<DocumentSaveMutationInput>> { ): Promise<MutationResult<DocumentSaveMutationInput>> {
await nodeManager.updateNode( await nodeManager.updateNode(
input.userId, input.userId,
@@ -28,7 +28,7 @@ export class DocumentSaveMutationHandler
const blocks = mapContentsToBlocks( const blocks = mapContentsToBlocks(
input.documentId, input.documentId,
input.content.content ?? [], input.content.content ?? [],
blocksMap, blocksMap
); );
attributes.content = blocks.reduce( attributes.content = blocks.reduce(
@@ -36,11 +36,11 @@ export class DocumentSaveMutationHandler
acc[block.id] = block; acc[block.id] = block;
return acc; return acc;
}, },
{} as Record<string, Block>, {} as Record<string, Block>
); );
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,18 +1,14 @@
import { LoginOutput } from '@/types/accounts'; import { LoginOutput } from '@/types/accounts';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { EmailLoginMutationInput } from '@/operations/mutations/email-login'; import { EmailLoginMutationInput } from '@/operations/mutations/email-login';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
export class EmailLoginMutationHandler export class EmailLoginMutationHandler
implements MutationHandler<EmailLoginMutationInput> implements MutationHandler<EmailLoginMutationInput>
{ {
async handleMutation( async handleMutation(
input: EmailLoginMutationInput, input: EmailLoginMutationInput
): Promise<MutationResult<EmailLoginMutationInput>> { ): Promise<MutationResult<EmailLoginMutationInput>> {
const server = await databaseManager.appDatabase const server = await databaseManager.appDatabase
.selectFrom('servers') .selectFrom('servers')
@@ -37,7 +33,7 @@ export class EmailLoginMutationHandler
{ {
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
}, }
); );
const changedTables: MutationChange[] = []; const changedTables: MutationChange[] = [];
@@ -77,7 +73,7 @@ export class EmailLoginMutationHandler
description: workspace.description, description: workspace.description,
user_id: workspace.user.id, user_id: workspace.user.id,
version_id: workspace.versionId, version_id: workspace.versionId,
})), }))
) )
.execute(); .execute();
@@ -89,7 +85,7 @@ export class EmailLoginMutationHandler
for (const workspace of data.workspaces) { for (const workspace of data.workspaces) {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
workspace.user.id, workspace.user.id
); );
const user = workspace.user.node; const user = workspace.user.node;

View File

@@ -2,17 +2,13 @@ import { LoginOutput } from '@/types/accounts';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { EmailRegisterMutationInput } from '@/operations/mutations/email-register'; import { EmailRegisterMutationInput } from '@/operations/mutations/email-register';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
export class EmailRegisterMutationHandler export class EmailRegisterMutationHandler
implements MutationHandler<EmailRegisterMutationInput> implements MutationHandler<EmailRegisterMutationInput>
{ {
handleMutation = async ( handleMutation = async (
input: EmailRegisterMutationInput, input: EmailRegisterMutationInput
): Promise<MutationResult<EmailRegisterMutationInput>> => { ): Promise<MutationResult<EmailRegisterMutationInput>> => {
const server = await databaseManager.appDatabase const server = await databaseManager.appDatabase
.selectFrom('servers') .selectFrom('servers')
@@ -38,7 +34,7 @@ export class EmailRegisterMutationHandler
{ {
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
}, }
); );
const changedTables: MutationChange[] = []; const changedTables: MutationChange[] = [];
@@ -78,7 +74,7 @@ export class EmailRegisterMutationHandler
description: workspace.description, description: workspace.description,
user_id: workspace.user.id, user_id: workspace.user.id,
version_id: workspace.versionId, version_id: workspace.versionId,
})), }))
) )
.execute(); .execute();
@@ -90,7 +86,7 @@ export class EmailRegisterMutationHandler
for (const workspace of data.workspaces) { for (const workspace of data.workspaces) {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
workspace.user.id, workspace.user.id
); );
const user = workspace.user.node; const user = workspace.user.node;

View File

@@ -1,7 +1,7 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { FieldCreateMutationInput } from '@/operations/mutations/field-create'; import { FieldCreateMutationInput } from '@/operations/mutations/field-create';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
@@ -9,7 +9,7 @@ export class FieldCreateMutationHandler
implements MutationHandler<FieldCreateMutationInput> implements MutationHandler<FieldCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: FieldCreateMutationInput, input: FieldCreateMutationInput
): Promise<MutationResult<FieldCreateMutationInput>> { ): Promise<MutationResult<FieldCreateMutationInput>> {
const fieldId = generateId(IdType.Field); const fieldId = generateId(IdType.Field);
await nodeManager.updateNode( await nodeManager.updateNode(
@@ -34,7 +34,7 @@ export class FieldCreateMutationHandler
}; };
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,18 +1,18 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { FileCreateMutationInput } from '@/operations/mutations/file-create'; import { FileCreateMutationInput } from '@/operations/mutations/file-create';
import { fileManager } from '@/main/file-manager'; import { fileManager } from '@/main/file-manager';
import { FileAttributes } from '@/registry'; import { FileAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class FileCreateMutationHandler export class FileCreateMutationHandler
implements MutationHandler<FileCreateMutationInput> implements MutationHandler<FileCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: FileCreateMutationInput, input: FileCreateMutationInput
): Promise<MutationResult<FileCreateMutationInput>> { ): Promise<MutationResult<FileCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const metadata = fileManager.getFileMetadata(input.filePath); const metadata = fileManager.getFileMetadata(input.filePath);
@@ -25,7 +25,7 @@ export class FileCreateMutationHandler
input.filePath, input.filePath,
id, id,
metadata.extension, metadata.extension,
input.userId, input.userId
); );
const attributes: FileAttributes = { const attributes: FileAttributes = {

View File

@@ -1,15 +1,15 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { FileDownloadMutationInput } from '@/operations/mutations/file-download'; import { FileDownloadMutationInput } from '@/operations/mutations/file-download';
export class FileDownloadMutationHandler export class FileDownloadMutationHandler
implements MutationHandler<FileDownloadMutationInput> implements MutationHandler<FileDownloadMutationInput>
{ {
async handleMutation( async handleMutation(
input: FileDownloadMutationInput, input: FileDownloadMutationInput
): Promise<MutationResult<FileDownloadMutationInput>> { ): Promise<MutationResult<FileDownloadMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const node = await workspaceDatabase const node = await workspaceDatabase

View File

@@ -1,7 +1,7 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { FolderCreateMutationInput } from '@/operations/mutations/folder-create'; import { FolderCreateMutationInput } from '@/operations/mutations/folder-create';
import { FolderAttributes } from '@/registry'; import { FolderAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
@@ -9,10 +9,10 @@ export class FolderCreateMutationHandler
implements MutationHandler<FolderCreateMutationInput> implements MutationHandler<FolderCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: FolderCreateMutationInput, input: FolderCreateMutationInput
): Promise<MutationResult<FolderCreateMutationInput>> { ): Promise<MutationResult<FolderCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const attributes: FolderAttributes = { const attributes: FolderAttributes = {

View File

@@ -1,4 +1,5 @@
import { MutationHandler, MutationMap } from '@/operations/mutations'; import { MutationMap } from '@/operations/mutations';
import { MutationHandler } from '@/main/types';
import { EmailLoginMutationHandler } from '@/main/handlers/mutations/email-login'; import { EmailLoginMutationHandler } from '@/main/handlers/mutations/email-login';
import { EmailRegisterMutationHandler } from '@/main/handlers/mutations/email-register'; import { EmailRegisterMutationHandler } from '@/main/handlers/mutations/email-register';
import { ViewCreateMutationHandler } from '@/main/handlers/mutations/view-create'; import { ViewCreateMutationHandler } from '@/main/handlers/mutations/view-create';

View File

@@ -1,7 +1,7 @@
import fs from 'fs'; import fs from 'fs';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { LogoutMutationInput } from '@/operations/mutations/logout'; import { LogoutMutationInput } from '@/operations/mutations/logout';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { import {
getAccountAvatarsDirectoryPath, getAccountAvatarsDirectoryPath,
getWorkspaceDirectoryPath, getWorkspaceDirectoryPath,
@@ -11,7 +11,7 @@ export class LogoutMutationHandler
implements MutationHandler<LogoutMutationInput> implements MutationHandler<LogoutMutationInput>
{ {
async handleMutation( async handleMutation(
input: LogoutMutationInput, input: LogoutMutationInput
): Promise<MutationResult<LogoutMutationInput>> { ): Promise<MutationResult<LogoutMutationInput>> {
const account = await databaseManager.appDatabase const account = await databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')

View File

@@ -1,6 +1,6 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { MarkNodeAsSeenMutationInput } from '@/operations/mutations/mark-node-as-seen'; import { MarkNodeAsSeenMutationInput } from '@/operations/mutations/mark-node-as-seen';
import { LocalUserNodeChangeData } from '@/types/sync'; import { LocalUserNodeChangeData } from '@/types/sync';
@@ -8,10 +8,10 @@ export class MarkNodeAsSeenMutationHandler
implements MutationHandler<MarkNodeAsSeenMutationInput> implements MutationHandler<MarkNodeAsSeenMutationInput>
{ {
async handleMutation( async handleMutation(
input: MarkNodeAsSeenMutationInput, input: MarkNodeAsSeenMutationInput
): Promise<MutationResult<MarkNodeAsSeenMutationInput>> { ): Promise<MutationResult<MarkNodeAsSeenMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const changeData: LocalUserNodeChangeData = { const changeData: LocalUserNodeChangeData = {

View File

@@ -2,27 +2,27 @@ import * as Y from 'yjs';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { EditorNodeTypes, NodeTypes } from '@/lib/constants'; import { EditorNodeTypes, NodeTypes } from '@/lib/constants';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { MessageCreateMutationInput } from '@/operations/mutations/message-create'; import { MessageCreateMutationInput } from '@/operations/mutations/message-create';
import { mapContentsToBlocks } from '@/lib/editor'; import { mapContentsToBlocks } from '@/lib/editor';
import { fileManager } from '@/main/file-manager'; import { fileManager } from '@/main/file-manager';
import { CreateDownload, CreateUpload } from '@/main/data/workspace/schema'; import { CreateDownload, CreateUpload } from '@/main/data/workspace/schema';
import { NodeAttributes } from '@/registry'; import {
import { Block, FileAttributes, MessageAttributes } from '@/registry'; NodeAttributes,
Block,
FileAttributes,
MessageAttributes,
} from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class MessageCreateMutationHandler export class MessageCreateMutationHandler
implements MutationHandler<MessageCreateMutationInput> implements MutationHandler<MessageCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: MessageCreateMutationInput, input: MessageCreateMutationInput
): Promise<MutationResult<MessageCreateMutationInput>> { ): Promise<MutationResult<MessageCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const nodeAttributes: NodeAttributes[] = []; const nodeAttributes: NodeAttributes[] = [];
@@ -34,7 +34,7 @@ export class MessageCreateMutationHandler
const blocks = mapContentsToBlocks( const blocks = mapContentsToBlocks(
messageId, messageId,
input.content.content ?? [], input.content.content ?? [],
new Map(), new Map()
); );
// check if there are nested nodes (files, pages, folders etc.) // check if there are nested nodes (files, pages, folders etc.)
@@ -56,7 +56,7 @@ export class MessageCreateMutationHandler
path, path,
fileId, fileId,
metadata.extension, metadata.extension,
input.userId, input.userId
); );
const fileDoc = new Y.Doc({ const fileDoc = new Y.Doc({
@@ -110,7 +110,7 @@ export class MessageCreateMutationHandler
acc[block.id] = block; acc[block.id] = block;
return acc; return acc;
}, },
{} as Record<string, Block>, {} as Record<string, Block>
), ),
reactions: {}, reactions: {},
}; };
@@ -123,7 +123,7 @@ export class MessageCreateMutationHandler
trx, trx,
input.userId, input.userId,
messageId, messageId,
nodeAttribute, nodeAttribute
); );
} }

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeAttributeDeleteMutationInput } from '@/operations/mutations/node-attribute-delete'; import { NodeAttributeDeleteMutationInput } from '@/operations/mutations/node-attribute-delete';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { unset } from 'lodash'; import { unset } from 'lodash';
@@ -7,7 +7,7 @@ export class NodeAttributeDeleteMutationHandler
implements MutationHandler<NodeAttributeDeleteMutationInput> implements MutationHandler<NodeAttributeDeleteMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeAttributeDeleteMutationInput, input: NodeAttributeDeleteMutationInput
): Promise<MutationResult<NodeAttributeDeleteMutationInput>> { ): Promise<MutationResult<NodeAttributeDeleteMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
unset(attributes, input.path); unset(attributes, input.path);

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeAttributeSetMutationInput } from '@/operations/mutations/node-attribute-set'; import { NodeAttributeSetMutationInput } from '@/operations/mutations/node-attribute-set';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { set } from 'lodash'; import { set } from 'lodash';
@@ -7,7 +7,7 @@ export class NodeAttributeSetMutationHandler
implements MutationHandler<NodeAttributeSetMutationInput> implements MutationHandler<NodeAttributeSetMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeAttributeSetMutationInput, input: NodeAttributeSetMutationInput
): Promise<MutationResult<NodeAttributeSetMutationInput>> { ): Promise<MutationResult<NodeAttributeSetMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
set(attributes, input.path, input.value); set(attributes, input.path, input.value);

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeCollaboratorCreateMutationInput } from '@/operations/mutations/node-collaborator-create'; import { NodeCollaboratorCreateMutationInput } from '@/operations/mutations/node-collaborator-create';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { set } from 'lodash'; import { set } from 'lodash';
@@ -7,7 +7,7 @@ export class NodeCollaboratorCreateMutationHandler
implements MutationHandler<NodeCollaboratorCreateMutationInput> implements MutationHandler<NodeCollaboratorCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeCollaboratorCreateMutationInput, input: NodeCollaboratorCreateMutationInput
): Promise<MutationResult<NodeCollaboratorCreateMutationInput>> { ): Promise<MutationResult<NodeCollaboratorCreateMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
for (const collaboratorId of input.collaboratorIds) { for (const collaboratorId of input.collaboratorIds) {

View File

@@ -1,5 +1,5 @@
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeCollaboratorDeleteMutationInput } from '@/operations/mutations/node-collaborator-delete'; import { NodeCollaboratorDeleteMutationInput } from '@/operations/mutations/node-collaborator-delete';
import { unset } from 'lodash'; import { unset } from 'lodash';
@@ -7,7 +7,7 @@ export class NodeCollaboratorDeleteMutationHandler
implements MutationHandler<NodeCollaboratorDeleteMutationInput> implements MutationHandler<NodeCollaboratorDeleteMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeCollaboratorDeleteMutationInput, input: NodeCollaboratorDeleteMutationInput
): Promise<MutationResult<NodeCollaboratorDeleteMutationInput>> { ): Promise<MutationResult<NodeCollaboratorDeleteMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
unset(attributes, `collaborators.${input.collaboratorId}`); unset(attributes, `collaborators.${input.collaboratorId}`);

View File

@@ -1,5 +1,5 @@
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeCollaboratorUpdateMutationInput } from '@/operations/mutations/node-collaborator-update'; import { NodeCollaboratorUpdateMutationInput } from '@/operations/mutations/node-collaborator-update';
import { set } from 'lodash'; import { set } from 'lodash';
@@ -7,7 +7,7 @@ export class NodeCollaboratorUpdateMutationHandler
implements MutationHandler<NodeCollaboratorUpdateMutationInput> implements MutationHandler<NodeCollaboratorUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeCollaboratorUpdateMutationInput, input: NodeCollaboratorUpdateMutationInput
): Promise<MutationResult<NodeCollaboratorUpdateMutationInput>> { ): Promise<MutationResult<NodeCollaboratorUpdateMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
set(attributes, `collaborators.${input.collaboratorId}`, input.role); set(attributes, `collaborators.${input.collaboratorId}`, input.role);

View File

@@ -1,11 +1,7 @@
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { fileManager } from '@/main/file-manager'; import { fileManager } from '@/main/file-manager';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { NodeDeleteMutationInput } from '@/operations/mutations/node-delete'; import { NodeDeleteMutationInput } from '@/operations/mutations/node-delete';
import { LocalDeleteNodeChangeData } from '@/types/sync'; import { LocalDeleteNodeChangeData } from '@/types/sync';
@@ -13,10 +9,10 @@ export class NodeDeleteMutationHandler
implements MutationHandler<NodeDeleteMutationInput> implements MutationHandler<NodeDeleteMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeDeleteMutationInput, input: NodeDeleteMutationInput
): Promise<MutationResult<NodeDeleteMutationInput>> { ): Promise<MutationResult<NodeDeleteMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const node = await workspaceDatabase const node = await workspaceDatabase

View File

@@ -1,12 +1,12 @@
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeReactionCreateMutationInput } from '@/operations/mutations/node-reaction-create'; import { NodeReactionCreateMutationInput } from '@/operations/mutations/node-reaction-create';
export class NodeReactionCreateMutationHandler export class NodeReactionCreateMutationHandler
implements MutationHandler<NodeReactionCreateMutationInput> implements MutationHandler<NodeReactionCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeReactionCreateMutationInput, input: NodeReactionCreateMutationInput
): Promise<MutationResult<NodeReactionCreateMutationInput>> { ): Promise<MutationResult<NodeReactionCreateMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
if (attributes.type !== 'message') { if (attributes.type !== 'message') {

View File

@@ -1,12 +1,12 @@
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { NodeReactionDeleteMutationInput } from '@/operations/mutations/node-reaction-delete'; import { NodeReactionDeleteMutationInput } from '@/operations/mutations/node-reaction-delete';
export class NodeReactionDeleteMutationHandler export class NodeReactionDeleteMutationHandler
implements MutationHandler<NodeReactionDeleteMutationInput> implements MutationHandler<NodeReactionDeleteMutationInput>
{ {
async handleMutation( async handleMutation(
input: NodeReactionDeleteMutationInput, input: NodeReactionDeleteMutationInput
): Promise<MutationResult<NodeReactionDeleteMutationInput>> { ): Promise<MutationResult<NodeReactionDeleteMutationInput>> {
await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => { await nodeManager.updateNode(input.userId, input.nodeId, (attributes) => {
if (attributes.type !== 'message') { if (attributes.type !== 'message') {

View File

@@ -1,18 +1,18 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { PageCreateMutationInput } from '@/operations/mutations/page-create'; import { PageCreateMutationInput } from '@/operations/mutations/page-create';
import { PageAttributes } from '@/registry'; import { PageAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class PageCreateMutationHandler export class PageCreateMutationHandler
implements MutationHandler<PageCreateMutationInput> implements MutationHandler<PageCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: PageCreateMutationInput, input: PageCreateMutationInput
): Promise<MutationResult<PageCreateMutationInput>> { ): Promise<MutationResult<PageCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const id = generateId(IdType.Page); const id = generateId(IdType.Page);

View File

@@ -1,18 +1,18 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { RecordCreateMutationInput } from '@/operations/mutations/record-create'; import { RecordCreateMutationInput } from '@/operations/mutations/record-create';
import { RecordAttributes } from '@/registry'; import { RecordAttributes } from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class RecordCreateMutationHandler export class RecordCreateMutationHandler
implements MutationHandler<RecordCreateMutationInput> implements MutationHandler<RecordCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: RecordCreateMutationInput, input: RecordCreateMutationInput
): Promise<MutationResult<RecordCreateMutationInput>> { ): Promise<MutationResult<RecordCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const id = generateId(IdType.Record); const id = generateId(IdType.Record);

View File

@@ -1,6 +1,6 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { SelectOptionCreateMutationInput } from '@/operations/mutations/select-option-create'; import { SelectOptionCreateMutationInput } from '@/operations/mutations/select-option-create';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
@@ -9,7 +9,7 @@ export class SelectOptionCreateMutationHandler
implements MutationHandler<SelectOptionCreateMutationInput> implements MutationHandler<SelectOptionCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: SelectOptionCreateMutationInput, input: SelectOptionCreateMutationInput
): Promise<MutationResult<SelectOptionCreateMutationInput>> { ): Promise<MutationResult<SelectOptionCreateMutationInput>> {
const id = generateId(IdType.SelectOption); const id = generateId(IdType.SelectOption);
await nodeManager.updateNode( await nodeManager.updateNode(
@@ -48,7 +48,7 @@ export class SelectOptionCreateMutationHandler
}; };
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,6 +1,6 @@
import axios from 'axios'; import axios from 'axios';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ServerCreateMutationInput } from '@/operations/mutations/server-create'; import { ServerCreateMutationInput } from '@/operations/mutations/server-create';
import { ServerConfig } from '@/types/servers'; import { ServerConfig } from '@/types/servers';
@@ -8,10 +8,10 @@ export class ServerCreateMutationHandler
implements MutationHandler<ServerCreateMutationInput> implements MutationHandler<ServerCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: ServerCreateMutationInput, input: ServerCreateMutationInput
): Promise<MutationResult<ServerCreateMutationInput>> { ): Promise<MutationResult<ServerCreateMutationInput>> {
const { data } = await axios.get<ServerConfig>( const { data } = await axios.get<ServerConfig>(
`http://${input.domain}/v1/config`, `http://${input.domain}/v1/config`
); );
await databaseManager.appDatabase await databaseManager.appDatabase

View File

@@ -1,17 +1,13 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { socketManager } from '@/main/sockets/socket-manager'; import { socketManager } from '@/main/sockets/socket-manager';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { ServerNodeDeleteMutationInput } from '@/operations/mutations/server-node-delete'; import { ServerNodeDeleteMutationInput } from '@/operations/mutations/server-node-delete';
export class ServerNodeDeleteMutationHandler export class ServerNodeDeleteMutationHandler
implements MutationHandler<ServerNodeDeleteMutationInput> implements MutationHandler<ServerNodeDeleteMutationInput>
{ {
public async handleMutation( public async handleMutation(
input: ServerNodeDeleteMutationInput, input: ServerNodeDeleteMutationInput
): Promise<MutationResult<ServerNodeDeleteMutationInput>> { ): Promise<MutationResult<ServerNodeDeleteMutationInput>> {
const changes: MutationChange[] = []; const changes: MutationChange[] = [];
@@ -22,7 +18,7 @@ export class ServerNodeDeleteMutationHandler
eb.and([ eb.and([
eb('account_id', '=', input.accountId), eb('account_id', '=', input.accountId),
eb('workspace_id', '=', input.workspaceId), eb('workspace_id', '=', input.workspaceId),
]), ])
) )
.executeTakeFirst(); .executeTakeFirst();

View File

@@ -1,7 +1,7 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { socketManager } from '@/main/sockets/socket-manager'; import { socketManager } from '@/main/sockets/socket-manager';
import { hasInsertChanges, hasUpdateChanges } from '@/main/utils'; import { hasInsertChanges, hasUpdateChanges } from '@/main/utils';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ServerNodeSyncMutationInput } from '@/operations/mutations/server-node-sync'; import { ServerNodeSyncMutationInput } from '@/operations/mutations/server-node-sync';
import { toUint8Array } from 'js-base64'; import { toUint8Array } from 'js-base64';
import * as Y from 'yjs'; import * as Y from 'yjs';
@@ -10,7 +10,7 @@ export class ServerNodeSyncMutationHandler
implements MutationHandler<ServerNodeSyncMutationInput> implements MutationHandler<ServerNodeSyncMutationInput>
{ {
public async handleMutation( public async handleMutation(
input: ServerNodeSyncMutationInput, input: ServerNodeSyncMutationInput
): Promise<MutationResult<ServerNodeSyncMutationInput>> { ): Promise<MutationResult<ServerNodeSyncMutationInput>> {
const workspace = await databaseManager.appDatabase const workspace = await databaseManager.appDatabase
.selectFrom('workspaces') .selectFrom('workspaces')
@@ -19,7 +19,7 @@ export class ServerNodeSyncMutationHandler
eb.and([ eb.and([
eb('account_id', '=', input.accountId), eb('account_id', '=', input.accountId),
eb('workspace_id', '=', input.workspaceId), eb('workspace_id', '=', input.workspaceId),
]), ])
) )
.executeTakeFirst(); .executeTakeFirst();

View File

@@ -1,13 +1,13 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { socketManager } from '@/main/sockets/socket-manager'; import { socketManager } from '@/main/sockets/socket-manager';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ServerUserNodeSyncMutationInput } from '@/operations/mutations/server-user-node-sync'; import { ServerUserNodeSyncMutationInput } from '@/operations/mutations/server-user-node-sync';
export class ServerUserNodeSyncMutationHandler export class ServerUserNodeSyncMutationHandler
implements MutationHandler<ServerUserNodeSyncMutationInput> implements MutationHandler<ServerUserNodeSyncMutationInput>
{ {
public async handleMutation( public async handleMutation(
input: ServerUserNodeSyncMutationInput, input: ServerUserNodeSyncMutationInput
): Promise<MutationResult<ServerUserNodeSyncMutationInput>> { ): Promise<MutationResult<ServerUserNodeSyncMutationInput>> {
const workspace = await databaseManager.appDatabase const workspace = await databaseManager.appDatabase
.selectFrom('workspaces') .selectFrom('workspaces')
@@ -16,7 +16,7 @@ export class ServerUserNodeSyncMutationHandler
eb.and([ eb.and([
eb('account_id', '=', input.accountId), eb('account_id', '=', input.accountId),
eb('workspace_id', '=', input.workspaceId), eb('workspace_id', '=', input.workspaceId),
]), ])
) )
.executeTakeFirst(); .executeTakeFirst();
@@ -51,7 +51,7 @@ export class ServerUserNodeSyncMutationHandler
mentions_count: input.mentionsCount, mentions_count: input.mentionsCount,
updated_at: input.updatedAt, updated_at: input.updatedAt,
version_id: input.versionId, version_id: input.versionId,
}), })
) )
.execute(); .execute();

View File

@@ -1,20 +1,24 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { SpaceCreateMutationInput } from '@/operations/mutations/space-create'; import { SpaceCreateMutationInput } from '@/operations/mutations/space-create';
import { NodeRole } from '@/lib/constants'; import { NodeRole } from '@/lib/constants';
import { ChannelAttributes, PageAttributes, SpaceAttributes } from '@/registry'; import {
ChannelAttributes,
PageAttributes,
SpaceAttributes,
} from '@colanode/core';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
export class SpaceCreateMutationHandler export class SpaceCreateMutationHandler
implements MutationHandler<SpaceCreateMutationInput> implements MutationHandler<SpaceCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: SpaceCreateMutationInput, input: SpaceCreateMutationInput
): Promise<MutationResult<SpaceCreateMutationInput>> { ): Promise<MutationResult<SpaceCreateMutationInput>> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const spaceId = generateId(IdType.Space); const spaceId = generateId(IdType.Space);
@@ -53,7 +57,7 @@ export class SpaceCreateMutationHandler
trx, trx,
input.userId, input.userId,
channelId, channelId,
channelAttributes, channelAttributes
); );
}); });

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { SpaceUpdateMutationInput } from '@/operations/mutations/space-update'; import { SpaceUpdateMutationInput } from '@/operations/mutations/space-update';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
@@ -6,7 +6,7 @@ export class SpaceUpdateMutationHandler
implements MutationHandler<SpaceUpdateMutationInput> implements MutationHandler<SpaceUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: SpaceUpdateMutationInput, input: SpaceUpdateMutationInput
): Promise<MutationResult<SpaceUpdateMutationInput>> { ): Promise<MutationResult<SpaceUpdateMutationInput>> {
await nodeManager.updateNode(input.userId, input.id, (attributes) => { await nodeManager.updateNode(input.userId, input.id, (attributes) => {
if (attributes.type !== 'space') { if (attributes.type !== 'space') {

View File

@@ -1,5 +1,5 @@
import { generateId, IdType } from '@/lib/id'; import { generateId, IdType } from '@/lib/id';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { ViewCreateMutationInput } from '@/operations/mutations/view-create'; import { ViewCreateMutationInput } from '@/operations/mutations/view-create';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { generateNodeIndex } from '@/lib/nodes'; import { generateNodeIndex } from '@/lib/nodes';
@@ -9,7 +9,7 @@ export class ViewCreateMutationHandler
implements MutationHandler<ViewCreateMutationInput> implements MutationHandler<ViewCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: ViewCreateMutationInput, input: ViewCreateMutationInput
): Promise<MutationResult<ViewCreateMutationInput>> { ): Promise<MutationResult<ViewCreateMutationInput>> {
const id = generateId(IdType.View); const id = generateId(IdType.View);
await nodeManager.updateNode( await nodeManager.updateNode(
@@ -37,7 +37,7 @@ export class ViewCreateMutationHandler
}; };
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { ViewDeleteMutationInput } from '@/operations/mutations/view-delete'; import { ViewDeleteMutationInput } from '@/operations/mutations/view-delete';
@@ -6,7 +6,7 @@ export class ViewDeleteMutationHandler
implements MutationHandler<ViewDeleteMutationInput> implements MutationHandler<ViewDeleteMutationInput>
{ {
async handleMutation( async handleMutation(
input: ViewDeleteMutationInput, input: ViewDeleteMutationInput
): Promise<MutationResult<ViewDeleteMutationInput>> { ): Promise<MutationResult<ViewDeleteMutationInput>> {
await nodeManager.updateNode( await nodeManager.updateNode(
input.userId, input.userId,
@@ -18,7 +18,7 @@ export class ViewDeleteMutationHandler
delete attributes.views[input.viewId]; delete attributes.views[input.viewId];
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,4 +1,4 @@
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { nodeManager } from '@/main/node-manager'; import { nodeManager } from '@/main/node-manager';
import { ViewUpdateMutationInput } from '@/operations/mutations/view-update'; import { ViewUpdateMutationInput } from '@/operations/mutations/view-update';
@@ -6,7 +6,7 @@ export class ViewUpdateMutationHandler
implements MutationHandler<ViewUpdateMutationInput> implements MutationHandler<ViewUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: ViewUpdateMutationInput, input: ViewUpdateMutationInput
): Promise<MutationResult<ViewUpdateMutationInput>> { ): Promise<MutationResult<ViewUpdateMutationInput>> {
await nodeManager.updateNode( await nodeManager.updateNode(
input.userId, input.userId,
@@ -18,7 +18,7 @@ export class ViewUpdateMutationHandler
attributes.views[input.view.id] = input.view; attributes.views[input.view.id] = input.view;
return attributes; return attributes;
}, }
); );
return { return {

View File

@@ -1,14 +1,14 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { WorkspaceCreateMutationInput } from '@/operations/mutations/workspace-create'; import { WorkspaceCreateMutationInput } from '@/operations/mutations/workspace-create';
import { MutationHandler, MutationResult } from '@/operations/mutations'; import { MutationHandler, MutationResult } from '@/main/types';
import { WorkspaceOutput } from '@/types/workspaces'; import { WorkspaceOutput } from '@/types/workspaces';
export class WorkspaceCreateMutationHandler export class WorkspaceCreateMutationHandler
implements MutationHandler<WorkspaceCreateMutationInput> implements MutationHandler<WorkspaceCreateMutationInput>
{ {
async handleMutation( async handleMutation(
input: WorkspaceCreateMutationInput, input: WorkspaceCreateMutationInput
): Promise<MutationResult<WorkspaceCreateMutationInput>> { ): Promise<MutationResult<WorkspaceCreateMutationInput>> {
const account = await databaseManager.appDatabase const account = await databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')
@@ -41,7 +41,7 @@ export class WorkspaceCreateMutationHandler
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
token: account.token, token: account.token,
}, }
); );
await databaseManager.appDatabase await databaseManager.appDatabase
@@ -60,7 +60,7 @@ export class WorkspaceCreateMutationHandler
.execute(); .execute();
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
data.user.id, data.user.id
); );
const user = data.user.node; const user = data.user.node;

View File

@@ -1,18 +1,14 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { WorkspaceUpdateMutationInput } from '@/operations/mutations/workspace-update'; import { WorkspaceUpdateMutationInput } from '@/operations/mutations/workspace-update';
import { import { MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { Workspace } from '@/types/workspaces'; import { Workspace } from '@/types/workspaces';
export class WorkspaceUpdateMutationHandler export class WorkspaceUpdateMutationHandler
implements MutationHandler<WorkspaceUpdateMutationInput> implements MutationHandler<WorkspaceUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: WorkspaceUpdateMutationInput, input: WorkspaceUpdateMutationInput
): Promise<MutationResult<WorkspaceUpdateMutationInput>> { ): Promise<MutationResult<WorkspaceUpdateMutationInput>> {
const account = await databaseManager.appDatabase const account = await databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')
@@ -45,7 +41,7 @@ export class WorkspaceUpdateMutationHandler
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
token: account.token, token: account.token,
}, }
); );
await databaseManager.appDatabase await databaseManager.appDatabase
@@ -61,7 +57,7 @@ export class WorkspaceUpdateMutationHandler
eb.and([ eb.and([
eb('account_id', '=', input.accountId), eb('account_id', '=', input.accountId),
eb('workspace_id', '=', input.id), eb('workspace_id', '=', input.id),
]), ])
) )
.execute(); .execute();

View File

@@ -1,18 +1,14 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { WorkspaceUserRoleUpdateMutationInput } from '@/operations/mutations/workspace-user-role-update'; import { WorkspaceUserRoleUpdateMutationInput } from '@/operations/mutations/workspace-user-role-update';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { WorkspaceUserRoleUpdateOutput } from '@/types/workspaces'; import { WorkspaceUserRoleUpdateOutput } from '@/types/workspaces';
export class WorkspaceUserRoleUpdateMutationHandler export class WorkspaceUserRoleUpdateMutationHandler
implements MutationHandler<WorkspaceUserRoleUpdateMutationInput> implements MutationHandler<WorkspaceUserRoleUpdateMutationInput>
{ {
async handleMutation( async handleMutation(
input: WorkspaceUserRoleUpdateMutationInput, input: WorkspaceUserRoleUpdateMutationInput
): Promise<MutationResult<WorkspaceUserRoleUpdateMutationInput>> { ): Promise<MutationResult<WorkspaceUserRoleUpdateMutationInput>> {
const workspace = await databaseManager.appDatabase const workspace = await databaseManager.appDatabase
.selectFrom('workspaces') .selectFrom('workspaces')
@@ -65,11 +61,11 @@ export class WorkspaceUserRoleUpdateMutationHandler
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
token: account.token, token: account.token,
}, }
); );
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
await workspaceDatabase await workspaceDatabase

View File

@@ -1,11 +1,7 @@
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { httpClient } from '@/lib/http-client'; import { httpClient } from '@/lib/http-client';
import { WorkspaceUsersInviteMutationInput } from '@/operations/mutations/workspace-users-invite'; import { WorkspaceUsersInviteMutationInput } from '@/operations/mutations/workspace-users-invite';
import { import { MutationChange, MutationHandler, MutationResult } from '@/main/types';
MutationChange,
MutationHandler,
MutationResult,
} from '@/operations/mutations';
import { WorkspaceUsersInviteOutput } from '@/types/workspaces'; import { WorkspaceUsersInviteOutput } from '@/types/workspaces';
import { CreateNode } from '@/main/data/workspace/schema'; import { CreateNode } from '@/main/data/workspace/schema';
@@ -13,7 +9,7 @@ export class WorkspaceUsersInviteMutationHandler
implements MutationHandler<WorkspaceUsersInviteMutationInput> implements MutationHandler<WorkspaceUsersInviteMutationInput>
{ {
async handleMutation( async handleMutation(
input: WorkspaceUsersInviteMutationInput, input: WorkspaceUsersInviteMutationInput
): Promise<MutationResult<WorkspaceUsersInviteMutationInput>> { ): Promise<MutationResult<WorkspaceUsersInviteMutationInput>> {
const workspace = await databaseManager.appDatabase const workspace = await databaseManager.appDatabase
.selectFrom('workspaces') .selectFrom('workspaces')
@@ -66,11 +62,11 @@ export class WorkspaceUsersInviteMutationHandler
serverDomain: server.domain, serverDomain: server.domain,
serverAttributes: server.attributes, serverAttributes: server.attributes,
token: account.token, token: account.token,
}, }
); );
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const usersToCreate: CreateNode[] = data.users.map((user) => { const usersToCreate: CreateNode[] = data.users.map((user) => {

View File

@@ -1,20 +1,20 @@
import { AccountListQueryInput } from '@/operations/queries/account-list'; import { AccountListQueryInput } from '@/operations/queries/account-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { Account } from '@/types/accounts'; import { Account } from '@/types/accounts';
import { SelectAccount } from '@/main/data/app/schema';
import { isEqual } from 'lodash';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { SelectAccount } from '@/main/data/app/schema';
import { isEqual } from 'lodash';
import { MutationChange } from '@/operations/mutations';
export class AccountListQueryHandler export class AccountListQueryHandler
implements QueryHandler<AccountListQueryInput> implements QueryHandler<AccountListQueryInput>
{ {
public async handleQuery( public async handleQuery(
_: AccountListQueryInput, _: AccountListQueryInput
): Promise<QueryResult<AccountListQueryInput>> { ): Promise<QueryResult<AccountListQueryInput>> {
const rows = await this.fetchAccounts(); const rows = await this.fetchAccounts();
return { return {
@@ -28,11 +28,11 @@ export class AccountListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
_: AccountListQueryInput, _: AccountListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<AccountListQueryInput>> { ): Promise<ChangeCheckResult<AccountListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => change.type === 'app' && change.table === 'accounts', (change) => change.type === 'app' && change.table === 'accounts'
) )
) { ) {
return { return {

View File

@@ -1,22 +1,22 @@
import { BreadcrumbListQueryInput } from '@/operations/queries/breadcrumb-list'; import { BreadcrumbListQueryInput } from '@/operations/queries/breadcrumb-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { BreadcrumbNode } from '@/types/workspaces'; import { BreadcrumbNode } from '@/types/workspaces';
import { mapNode } from '@/lib/nodes'; import { mapNode } from '@/main/utils';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
export class BreadcrumbListQueryHandler export class BreadcrumbListQueryHandler
implements QueryHandler<BreadcrumbListQueryInput> implements QueryHandler<BreadcrumbListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: BreadcrumbListQueryInput, input: BreadcrumbListQueryInput
): Promise<QueryResult<BreadcrumbListQueryInput>> { ): Promise<QueryResult<BreadcrumbListQueryInput>> {
const rows = await this.fetchNodes(input); const rows = await this.fetchNodes(input);
return { return {
@@ -30,14 +30,14 @@ export class BreadcrumbListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: BreadcrumbListQueryInput, input: BreadcrumbListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<BreadcrumbListQueryInput>> { ): Promise<ChangeCheckResult<BreadcrumbListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -64,10 +64,10 @@ export class BreadcrumbListQueryHandler
} }
private async fetchNodes( private async fetchNodes(
input: BreadcrumbListQueryInput, input: BreadcrumbListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const query = sql<SelectNode>` const query = sql<SelectNode>`
@@ -90,7 +90,7 @@ export class BreadcrumbListQueryHandler
private buildBreadcrumbNodes = ( private buildBreadcrumbNodes = (
nodeId: string, nodeId: string,
rows: SelectNode[], rows: SelectNode[]
): BreadcrumbNode[] => { ): BreadcrumbNode[] => {
const breadcrumbNodes: BreadcrumbNode[] = []; const breadcrumbNodes: BreadcrumbNode[] = [];

View File

@@ -1,19 +1,19 @@
import { ChatGetQueryInput } from '@/operations/queries/chat-get'; import { ChatGetQueryInput } from '@/operations/queries/chat-get';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { mapNode } from '@/main/utils';
import { SelectNode } from '@/main/data/workspace/schema';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { mapNode } from '@/lib/nodes';
import { SelectNode } from '@/main/data/workspace/schema';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { ChatNode } from '@/types/chats'; import { ChatNode } from '@/types/chats';
export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> { export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> {
async handleQuery( async handleQuery(
input: ChatGetQueryInput, input: ChatGetQueryInput
): Promise<QueryResult<ChatGetQueryInput>> { ): Promise<QueryResult<ChatGetQueryInput>> {
const chat = await this.fetchChat(input); const chat = await this.fetchChat(input);
if (!chat) { if (!chat) {
@@ -36,14 +36,14 @@ export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> {
async checkForChanges( async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: ChatGetQueryInput, input: ChatGetQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<ChatGetQueryInput>> { ): Promise<ChangeCheckResult<ChatGetQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -86,10 +86,10 @@ export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> {
} }
private async fetchChat( private async fetchChat(
input: ChatGetQueryInput, input: ChatGetQueryInput
): Promise<SelectNode | null> { ): Promise<SelectNode | null> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const chat = await workspaceDatabase const chat = await workspaceDatabase
@@ -103,10 +103,10 @@ export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> {
private async fetchCollaborators( private async fetchCollaborators(
input: ChatGetQueryInput, input: ChatGetQueryInput,
chat: SelectNode, chat: SelectNode
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
if (!chat.attributes) { if (!chat.attributes) {
@@ -144,7 +144,7 @@ export class ChatGetQueryHandler implements QueryHandler<ChatGetQueryInput> {
private buildChat = ( private buildChat = (
chat: SelectNode, chat: SelectNode,
collaborators: SelectNode[], collaborators: SelectNode[]
): ChatNode | null => { ): ChatNode | null => {
const collaborator = mapNode(collaborators[0]); const collaborator = mapNode(collaborators[0]);
if (collaborator.attributes.type !== 'user') { if (collaborator.attributes.type !== 'user') {

View File

@@ -5,22 +5,21 @@ import {
DocumentGetQueryOutput, DocumentGetQueryOutput,
} from '@/operations/queries/document-get'; } from '@/operations/queries/document-get';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { SelectNode } from '@/main/data/workspace/schema';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { NodeAttributes } from '@colanode/core';
import { SelectNode } from '@/main/data/workspace/schema';
import { MutationChange } from '@/operations/mutations';
import { NodeAttributes } from '@/registry';
import { mapBlocksToContents } from '@/lib/editor'; import { mapBlocksToContents } from '@/lib/editor';
export class DocumentGetQueryHandler export class DocumentGetQueryHandler
implements QueryHandler<DocumentGetQueryInput> implements QueryHandler<DocumentGetQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: DocumentGetQueryInput, input: DocumentGetQueryInput
): Promise<QueryResult<DocumentGetQueryInput>> { ): Promise<QueryResult<DocumentGetQueryInput>> {
const document = await this.fetchDocument(input); const document = await this.fetchDocument(input);
return { return {
@@ -34,14 +33,14 @@ export class DocumentGetQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: DocumentGetQueryInput, input: DocumentGetQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<DocumentGetQueryInput>> { ): Promise<ChangeCheckResult<DocumentGetQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -68,10 +67,10 @@ export class DocumentGetQueryHandler
} }
private async fetchDocument( private async fetchDocument(
input: DocumentGetQueryInput, input: DocumentGetQueryInput
): Promise<SelectNode | undefined> { ): Promise<SelectNode | undefined> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
return workspaceDatabase return workspaceDatabase
@@ -82,7 +81,7 @@ export class DocumentGetQueryHandler
} }
private buildOutput( private buildOutput(
document: SelectNode | null | undefined, document: SelectNode | null | undefined
): DocumentGetQueryOutput { ): DocumentGetQueryOutput {
if (!document) { if (!document) {
return { return {

View File

@@ -1,11 +1,11 @@
import { FileGetQueryInput } from '@/operations/queries/file-get'; import { FileGetQueryInput } from '@/operations/queries/file-get';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { FileDetails } from '@/types/files'; import { FileDetails } from '@/types/files';
@@ -22,7 +22,7 @@ interface FileRow {
export class FileGetQueryHandler implements QueryHandler<FileGetQueryInput> { export class FileGetQueryHandler implements QueryHandler<FileGetQueryInput> {
public async handleQuery( public async handleQuery(
input: FileGetQueryInput, input: FileGetQueryInput
): Promise<QueryResult<FileGetQueryInput>> { ): Promise<QueryResult<FileGetQueryInput>> {
const row = await this.fetchFile(input); const row = await this.fetchFile(input);
@@ -37,14 +37,14 @@ export class FileGetQueryHandler implements QueryHandler<FileGetQueryInput> {
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: FileGetQueryInput, input: FileGetQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<FileGetQueryInput>> { ): Promise<ChangeCheckResult<FileGetQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
(change.table === 'nodes' || change.table === 'downloads') && (change.table === 'nodes' || change.table === 'downloads') &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -71,19 +71,19 @@ export class FileGetQueryHandler implements QueryHandler<FileGetQueryInput> {
} }
private async fetchFile( private async fetchFile(
input: FileGetQueryInput, input: FileGetQueryInput
): Promise<FileRow | undefined> { ): Promise<FileRow | undefined> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const row = await workspaceDatabase const row = await workspaceDatabase
.selectFrom('nodes as file') .selectFrom('nodes as file')
.leftJoin('downloads as file_downloads', (join) => .leftJoin('downloads as file_downloads', (join) =>
join.onRef('file.id', '=', 'file_downloads.node_id'), join.onRef('file.id', '=', 'file_downloads.node_id')
) )
.leftJoin('nodes as created_by', (join) => .leftJoin('nodes as created_by', (join) =>
join.onRef('file.created_by', '=', 'created_by.id'), join.onRef('file.created_by', '=', 'created_by.id')
) )
.select([ .select([
'file.id', 'file.id',

View File

@@ -1,11 +1,11 @@
import { FileListQueryInput } from '@/operations/queries/file-list'; import { FileListQueryInput } from '@/operations/queries/file-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { MutationChange } from '@/operations/mutations';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
@@ -23,7 +23,7 @@ interface FileRow {
export class FileListQueryHandler implements QueryHandler<FileListQueryInput> { export class FileListQueryHandler implements QueryHandler<FileListQueryInput> {
public async handleQuery( public async handleQuery(
input: FileListQueryInput, input: FileListQueryInput
): Promise<QueryResult<FileListQueryInput>> { ): Promise<QueryResult<FileListQueryInput>> {
const files = await this.fetchFiles(input); const files = await this.fetchFiles(input);
@@ -38,14 +38,14 @@ export class FileListQueryHandler implements QueryHandler<FileListQueryInput> {
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: FileListQueryInput, input: FileListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<FileListQueryInput>> { ): Promise<ChangeCheckResult<FileListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
(change.table === 'nodes' || change.table === 'downloads') && (change.table === 'nodes' || change.table === 'downloads') &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -73,14 +73,14 @@ export class FileListQueryHandler implements QueryHandler<FileListQueryInput> {
private async fetchFiles(input: FileListQueryInput): Promise<FileRow[]> { private async fetchFiles(input: FileListQueryInput): Promise<FileRow[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const offset = input.page * input.count; const offset = input.page * input.count;
const files = await workspaceDatabase const files = await workspaceDatabase
.selectFrom('nodes') .selectFrom('nodes')
.leftJoin('downloads', (join) => .leftJoin('downloads', (join) =>
join.onRef('nodes.id', '=', 'downloads.node_id'), join.onRef('nodes.id', '=', 'downloads.node_id')
) )
.select([ .select([
'nodes.id', 'nodes.id',
@@ -95,7 +95,7 @@ export class FileListQueryHandler implements QueryHandler<FileListQueryInput> {
eb.and([ eb.and([
eb('parent_id', '=', input.parentId), eb('parent_id', '=', input.parentId),
eb('type', '=', NodeTypes.File), eb('type', '=', NodeTypes.File),
]), ])
) )
.orderBy('id', 'asc') .orderBy('id', 'asc')
.limit(input.count) .limit(input.count)

View File

@@ -1,4 +1,5 @@
import { QueryHandler, QueryMap } from '@/operations/queries'; import { QueryMap } from '@/operations/queries';
import { QueryHandler } from '@/main/types';
import { AccountListQueryHandler } from '@/main/handlers/queries/accounts-list'; import { AccountListQueryHandler } from '@/main/handlers/queries/accounts-list';
import { BreadcrumbListQueryHandler } from '@/main/handlers/queries/breadcrumb-list'; import { BreadcrumbListQueryHandler } from '@/main/handlers/queries/breadcrumb-list';
import { MessageListQueryHandler } from '@/main/handlers/queries/message-list'; import { MessageListQueryHandler } from '@/main/handlers/queries/message-list';

View File

@@ -1,15 +1,15 @@
import { MessageListQueryInput } from '@/operations/queries/message-list'; import { MessageListQueryInput } from '@/operations/queries/message-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { MutationChange } from '@/operations/mutations';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { MessageNode, MessageReactionCount } from '@/types/messages'; import { MessageNode, MessageReactionCount } from '@/types/messages';
import { mapNode } from '@/lib/nodes'; import { mapNode } from '@/main/utils';
import { UserNode } from '@/types/users'; import { UserNode } from '@/types/users';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
@@ -19,7 +19,7 @@ export class MessageListQueryHandler
implements QueryHandler<MessageListQueryInput> implements QueryHandler<MessageListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: MessageListQueryInput, input: MessageListQueryInput
): Promise<QueryResult<MessageListQueryInput>> { ): Promise<QueryResult<MessageListQueryInput>> {
const messages = await this.fetchMesssages(input); const messages = await this.fetchMesssages(input);
const authors = await this.fetchAuthors(input, messages); const authors = await this.fetchAuthors(input, messages);
@@ -36,14 +36,14 @@ export class MessageListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: MessageListQueryInput, input: MessageListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<MessageListQueryInput>> { ): Promise<ChangeCheckResult<MessageListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -73,10 +73,10 @@ export class MessageListQueryHandler
} }
private async fetchMesssages( private async fetchMesssages(
input: MessageListQueryInput, input: MessageListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const offset = input.page * input.count; const offset = input.page * input.count;
@@ -87,7 +87,7 @@ export class MessageListQueryHandler
eb.and([ eb.and([
eb('parent_id', '=', input.conversationId), eb('parent_id', '=', input.conversationId),
eb('type', '=', NodeTypes.Message), eb('type', '=', NodeTypes.Message),
]), ])
) )
.orderBy('id', 'desc') .orderBy('id', 'desc')
.limit(input.count) .limit(input.count)
@@ -99,14 +99,14 @@ export class MessageListQueryHandler
private async fetchAuthors( private async fetchAuthors(
input: MessageListQueryInput, input: MessageListQueryInput,
messages: SelectNode[], messages: SelectNode[]
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
if (messages.length === 0) { if (messages.length === 0) {
return []; return [];
} }
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const authorIds = messages.map((message) => message.created_by); const authorIds = messages.map((message) => message.created_by);
@@ -122,7 +122,7 @@ export class MessageListQueryHandler
private buildMessages = ( private buildMessages = (
userId: string, userId: string,
messageRows: SelectNode[], messageRows: SelectNode[],
authorRows: SelectNode[], authorRows: SelectNode[]
): MessageNode[] => { ): MessageNode[] => {
const messages: MessageNode[] = []; const messages: MessageNode[] = [];
const authorMap = new Map<string, UserNode>(); const authorMap = new Map<string, UserNode>();
@@ -174,7 +174,7 @@ export class MessageListQueryHandler
}, },
content: mapBlocksToContents( content: mapBlocksToContents(
messageNode.id, messageNode.id,
Object.values(messageNode.attributes.content ?? {}), Object.values(messageNode.attributes.content ?? {})
), ),
reactionCounts, reactionCounts,
}; };

View File

@@ -1,17 +1,17 @@
import { NodeCollaboratorListQueryInput } from '@/operations/queries/node-collaborator-list'; import { NodeCollaboratorListQueryInput } from '@/operations/queries/node-collaborator-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { import {
InheritNodeCollaboratorsGroup, InheritNodeCollaboratorsGroup,
NodeCollaboratorsWrapper, NodeCollaboratorsWrapper,
NodeCollaborator, NodeCollaborator,
} from '@/types/nodes'; } from '@/types/nodes';
import { NodeAttributes } from '@/registry'; import { NodeAttributes } from '@colanode/core';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
type ExtractedNodeCollaborator = { type ExtractedNodeCollaborator = {
@@ -29,17 +29,17 @@ export class NodeCollaboratorListQueryHandler
implements QueryHandler<NodeCollaboratorListQueryInput> implements QueryHandler<NodeCollaboratorListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: NodeCollaboratorListQueryInput, input: NodeCollaboratorListQueryInput
): Promise<QueryResult<NodeCollaboratorListQueryInput>> { ): Promise<QueryResult<NodeCollaboratorListQueryInput>> {
const ancestors = await this.fetchAncestors(input); const ancestors = await this.fetchAncestors(input);
const extractedCollaborators = this.extractCollaborators(ancestors); const extractedCollaborators = this.extractCollaborators(ancestors);
const collaboratorIds = extractedCollaborators.map( const collaboratorIds = extractedCollaborators.map(
(collaborator) => collaborator.collaboratorId, (collaborator) => collaborator.collaboratorId
); );
const collaboratorNodes = await this.fetchCollaborators( const collaboratorNodes = await this.fetchCollaborators(
input, input,
collaboratorIds, collaboratorIds
); );
return { return {
@@ -47,7 +47,7 @@ export class NodeCollaboratorListQueryHandler
input.nodeId, input.nodeId,
ancestors, ancestors,
collaboratorNodes, collaboratorNodes,
extractedCollaborators, extractedCollaborators
), ),
state: { state: {
ancestors, ancestors,
@@ -60,14 +60,14 @@ export class NodeCollaboratorListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: NodeCollaboratorListQueryInput, input: NodeCollaboratorListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<NodeCollaboratorListQueryInput>> { ): Promise<ChangeCheckResult<NodeCollaboratorListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -78,12 +78,12 @@ export class NodeCollaboratorListQueryHandler
const ancestors = await this.fetchAncestors(input); const ancestors = await this.fetchAncestors(input);
const extractedCollaborators = this.extractCollaborators(ancestors); const extractedCollaborators = this.extractCollaborators(ancestors);
const collaboratorIds = extractedCollaborators.map( const collaboratorIds = extractedCollaborators.map(
(collaborator) => collaborator.collaboratorId, (collaborator) => collaborator.collaboratorId
); );
const collaboratorNodes = await this.fetchCollaborators( const collaboratorNodes = await this.fetchCollaborators(
input, input,
collaboratorIds, collaboratorIds
); );
if ( if (
@@ -103,7 +103,7 @@ export class NodeCollaboratorListQueryHandler
input.nodeId, input.nodeId,
ancestors, ancestors,
collaboratorNodes, collaboratorNodes,
extractedCollaborators, extractedCollaborators
), ),
state: { state: {
ancestors, ancestors,
@@ -115,10 +115,10 @@ export class NodeCollaboratorListQueryHandler
} }
private async fetchAncestors( private async fetchAncestors(
input: NodeCollaboratorListQueryInput, input: NodeCollaboratorListQueryInput
): Promise<NodeWithAttributesRow[]> { ): Promise<NodeWithAttributesRow[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const result = await workspaceDatabase const result = await workspaceDatabase
@@ -133,7 +133,7 @@ export class NodeCollaboratorListQueryHandler
} }
private extractCollaborators( private extractCollaborators(
nodes: NodeWithAttributesRow[], nodes: NodeWithAttributesRow[]
): ExtractedNodeCollaborator[] { ): ExtractedNodeCollaborator[] {
const map: Map<string, ExtractedNodeCollaborator> = new Map(); const map: Map<string, ExtractedNodeCollaborator> = new Map();
@@ -170,14 +170,14 @@ export class NodeCollaboratorListQueryHandler
private async fetchCollaborators( private async fetchCollaborators(
input: NodeCollaboratorListQueryInput, input: NodeCollaboratorListQueryInput,
collaboratorIds: string[], collaboratorIds: string[]
): Promise<NodeWithAttributesRow[]> { ): Promise<NodeWithAttributesRow[]> {
if (collaboratorIds.length === 0) { if (collaboratorIds.length === 0) {
return []; return [];
} }
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const result = await workspaceDatabase const result = await workspaceDatabase
@@ -193,7 +193,7 @@ export class NodeCollaboratorListQueryHandler
nodeId: string, nodeId: string,
ancestors: NodeWithAttributesRow[], ancestors: NodeWithAttributesRow[],
collaboratorNodes: NodeWithAttributesRow[], collaboratorNodes: NodeWithAttributesRow[],
extractedCollaborators: ExtractedNodeCollaborator[], extractedCollaborators: ExtractedNodeCollaborator[]
): NodeCollaboratorsWrapper => { ): NodeCollaboratorsWrapper => {
const direct: NodeCollaborator[] = []; const direct: NodeCollaborator[] = [];
const inherit: InheritNodeCollaboratorsGroup[] = []; const inherit: InheritNodeCollaboratorsGroup[] = [];
@@ -202,7 +202,7 @@ export class NodeCollaboratorListQueryHandler
for (const extractedCollaborator of extractedCollaborators) { for (const extractedCollaborator of extractedCollaborators) {
const collaboratorNode = collaboratorNodes.find( const collaboratorNode = collaboratorNodes.find(
(row) => row.id === extractedCollaborator.collaboratorId, (row) => row.id === extractedCollaborator.collaboratorId
); );
if (!collaboratorNode) { if (!collaboratorNode) {

View File

@@ -1,22 +1,22 @@
import { NodeCollaboratorSearchQueryInput } from '@/operations/queries/node-collaborator-search'; import { NodeCollaboratorSearchQueryInput } from '@/operations/queries/node-collaborator-search';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { NodeCollaborator } from '@/types/nodes'; import { NodeCollaborator } from '@/types/nodes';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
export class NodeCollaboratorSearchQueryHandler export class NodeCollaboratorSearchQueryHandler
implements QueryHandler<NodeCollaboratorSearchQueryInput> implements QueryHandler<NodeCollaboratorSearchQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: NodeCollaboratorSearchQueryInput, input: NodeCollaboratorSearchQueryInput
): Promise<QueryResult<NodeCollaboratorSearchQueryInput>> { ): Promise<QueryResult<NodeCollaboratorSearchQueryInput>> {
if (input.searchQuery.length === 0) { if (input.searchQuery.length === 0) {
return { return {
@@ -39,14 +39,14 @@ export class NodeCollaboratorSearchQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: NodeCollaboratorSearchQueryInput, input: NodeCollaboratorSearchQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<NodeCollaboratorSearchQueryInput>> { ): Promise<ChangeCheckResult<NodeCollaboratorSearchQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -73,14 +73,14 @@ export class NodeCollaboratorSearchQueryHandler
} }
private async fetchNodes( private async fetchNodes(
input: NodeCollaboratorSearchQueryInput, input: NodeCollaboratorSearchQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
if (input.searchQuery.length === 0) { if (input.searchQuery.length === 0) {
return []; return [];
} }
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const query = sql<SelectNode>` const query = sql<SelectNode>`
@@ -93,7 +93,7 @@ export class NodeCollaboratorSearchQueryHandler
input.excluded.length > 0 input.excluded.length > 0
? sql`AND n.id NOT IN (${sql.join( ? sql`AND n.id NOT IN (${sql.join(
input.excluded.map((id) => sql`${id}`), input.excluded.map((id) => sql`${id}`),
sql`, `, sql`, `
)})` )})`
: sql`` : sql``
} }

View File

@@ -1,18 +1,18 @@
import { NodeGetQueryInput } from '@/operations/queries/node-get'; import { NodeGetQueryInput } from '@/operations/queries/node-get';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { mapNode } from '@/main/utils';
import { SelectNode } from '@/main/data/workspace/schema';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { mapNode } from '@/lib/nodes';
import { SelectNode } from '@/main/data/workspace/schema';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> { export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> {
public async handleQuery( public async handleQuery(
input: NodeGetQueryInput, input: NodeGetQueryInput
): Promise<QueryResult<NodeGetQueryInput>> { ): Promise<QueryResult<NodeGetQueryInput>> {
const row = await this.fetchNode(input); const row = await this.fetchNode(input);
@@ -27,14 +27,14 @@ export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> {
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: NodeGetQueryInput, input: NodeGetQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<NodeGetQueryInput>> { ): Promise<ChangeCheckResult<NodeGetQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -61,10 +61,10 @@ export class NodeGetQueryHandler implements QueryHandler<NodeGetQueryInput> {
} }
private async fetchNode( private async fetchNode(
input: NodeGetQueryInput, input: NodeGetQueryInput
): Promise<SelectNode | undefined> { ): Promise<SelectNode | undefined> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const row = await workspaceDatabase const row = await workspaceDatabase

View File

@@ -1,11 +1,11 @@
import { RecordListQueryInput } from '@/operations/queries/record-list'; import { RecordListQueryInput } from '@/operations/queries/record-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { MutationChange } from '@/operations/mutations';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { import {
@@ -25,9 +25,9 @@ import {
ViewSortAttributes, ViewSortAttributes,
DatabaseNode, DatabaseNode,
RecordNode, RecordNode,
} from '@/registry'; } from '@colanode/core';
import { isStringArray } from '@/lib/utils'; import { isStringArray } from '@/lib/utils';
import { mapNode } from '@/lib/nodes'; import { mapNode } from '@/main/utils';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
@@ -35,7 +35,7 @@ export class RecordListQueryHandler
implements QueryHandler<RecordListQueryInput> implements QueryHandler<RecordListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: RecordListQueryInput, input: RecordListQueryInput
): Promise<QueryResult<RecordListQueryInput>> { ): Promise<QueryResult<RecordListQueryInput>> {
const rows = await this.fetchRecords(input); const rows = await this.fetchRecords(input);
@@ -50,14 +50,14 @@ export class RecordListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: RecordListQueryInput, input: RecordListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<RecordListQueryInput>> { ): Promise<ChangeCheckResult<RecordListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -84,16 +84,16 @@ export class RecordListQueryHandler
} }
private async fetchRecords( private async fetchRecords(
input: RecordListQueryInput, input: RecordListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const database = await this.fetchDatabase(input.userId, input.databaseId); const database = await this.fetchDatabase(input.userId, input.databaseId);
const filterQuery = this.buildFiltersQuery( const filterQuery = this.buildFiltersQuery(
input.filters, input.filters,
database.attributes.fields, database.attributes.fields
); );
const orderByQuery = `ORDER BY ${input.sorts.length > 0 ? this.buildSortOrdersQuery(input.sorts, database.attributes.fields) : 'n."index" ASC'}`; const orderByQuery = `ORDER BY ${input.sorts.length > 0 ? this.buildSortOrdersQuery(input.sorts, database.attributes.fields) : 'n."index" ASC'}`;
@@ -143,7 +143,7 @@ export class RecordListQueryHandler
private async fetchDatabase( private async fetchDatabase(
userId: string, userId: string,
databaseId: string, databaseId: string
): Promise<DatabaseNode> { ): Promise<DatabaseNode> {
const workspaceDatabase = const workspaceDatabase =
await databaseManager.getWorkspaceDatabase(userId); await databaseManager.getWorkspaceDatabase(userId);
@@ -164,7 +164,7 @@ export class RecordListQueryHandler
private buildFiltersQuery = ( private buildFiltersQuery = (
filters: ViewFilterAttributes[], filters: ViewFilterAttributes[],
fields: Record<string, FieldAttributes>, fields: Record<string, FieldAttributes>
): string => { ): string => {
if (filters.length === 0) { if (filters.length === 0) {
return ''; return '';
@@ -183,7 +183,7 @@ export class RecordListQueryHandler
private buildFilterQuery = ( private buildFilterQuery = (
filter: ViewFilterAttributes, filter: ViewFilterAttributes,
fields: Record<string, FieldAttributes>, fields: Record<string, FieldAttributes>
): string | null => { ): string | null => {
if (filter.type === 'group') { if (filter.type === 'group') {
return null; return null;
@@ -228,7 +228,7 @@ export class RecordListQueryHandler
buildBooleanFilterQuery = ( buildBooleanFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: BooleanFieldAttributes, field: BooleanFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_true') { if (filter.operator === 'is_true') {
return `json_extract(n.attributes, '$.fields.${field.id}.value') = true`; return `json_extract(n.attributes, '$.fields.${field.id}.value') = true`;
@@ -243,7 +243,7 @@ export class RecordListQueryHandler
private buildNumberFilterQuery = ( private buildNumberFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: NumberFieldAttributes, field: NumberFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -296,7 +296,7 @@ export class RecordListQueryHandler
private buildTextFilterQuery = ( private buildTextFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: TextFieldAttributes, field: TextFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -354,7 +354,7 @@ export class RecordListQueryHandler
private buildEmailFilterQuery = ( private buildEmailFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: EmailFieldAttributes, field: EmailFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -412,7 +412,7 @@ export class RecordListQueryHandler
private buildPhoneFilterQuery = ( private buildPhoneFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: PhoneFieldAttributes, field: PhoneFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -470,7 +470,7 @@ export class RecordListQueryHandler
private buildUrlFilterQuery = ( private buildUrlFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: UrlFieldAttributes, field: UrlFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -528,7 +528,7 @@ export class RecordListQueryHandler
private buildSelectFilterQuery = ( private buildSelectFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: SelectFieldAttributes, field: SelectFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -559,7 +559,7 @@ export class RecordListQueryHandler
private buildMultiSelectFilterQuery = ( private buildMultiSelectFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: MultiSelectFieldAttributes, field: MultiSelectFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return `json_extract(n.attributes, '$.fields.${field.id}.value') IS NULL OR json_array_length(json_extract(n.attributes, '$.fields.${field.id}.value')) = 0`; return `json_extract(n.attributes, '$.fields.${field.id}.value') IS NULL OR json_array_length(json_extract(n.attributes, '$.fields.${field.id}.value')) = 0`;
@@ -590,7 +590,7 @@ export class RecordListQueryHandler
private buildDateFilterQuery = ( private buildDateFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: DateFieldAttributes, field: DateFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return this.buildIsEmptyFilterQuery(field.id); return this.buildIsEmptyFilterQuery(field.id);
@@ -648,7 +648,7 @@ export class RecordListQueryHandler
private buildCreatedAtFilterQuery = ( private buildCreatedAtFilterQuery = (
filter: ViewFieldFilterAttributes, filter: ViewFieldFilterAttributes,
field: CreatedAtFieldAttributes, _: CreatedAtFieldAttributes
): string | null => { ): string | null => {
if (filter.operator === 'is_empty') { if (filter.operator === 'is_empty') {
return `n.created_at IS NULL`; return `n.created_at IS NULL`;
@@ -718,7 +718,7 @@ export class RecordListQueryHandler
private buildSortOrdersQuery = ( private buildSortOrdersQuery = (
sorts: ViewSortAttributes[], sorts: ViewSortAttributes[],
fields: Record<string, FieldAttributes>, fields: Record<string, FieldAttributes>
): string => { ): string => {
return sorts return sorts
.map((sort) => this.buildSortOrderQuery(sort, fields)) .map((sort) => this.buildSortOrderQuery(sort, fields))
@@ -728,7 +728,7 @@ export class RecordListQueryHandler
private buildSortOrderQuery = ( private buildSortOrderQuery = (
sort: ViewSortAttributes, sort: ViewSortAttributes,
fields: Record<string, FieldAttributes>, fields: Record<string, FieldAttributes>
): string | null => { ): string | null => {
const field = fields[sort.fieldId]; const field = fields[sort.fieldId];
if (!field) { if (!field) {

View File

@@ -1,12 +1,12 @@
import { ServerListQueryInput } from '@/operations/queries/server-list'; import { ServerListQueryInput } from '@/operations/queries/server-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { SelectServer } from '@/main/data/app/schema';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { SelectServer } from '@/main/data/app/schema';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { Server } from '@/types/servers'; import { Server } from '@/types/servers';
@@ -14,7 +14,7 @@ export class ServerListQueryHandler
implements QueryHandler<ServerListQueryInput> implements QueryHandler<ServerListQueryInput>
{ {
async handleQuery( async handleQuery(
_: ServerListQueryInput, _: ServerListQueryInput
): Promise<QueryResult<ServerListQueryInput>> { ): Promise<QueryResult<ServerListQueryInput>> {
const rows = await this.fetchServers(); const rows = await this.fetchServers();
return { return {
@@ -28,11 +28,11 @@ export class ServerListQueryHandler
async checkForChanges( async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
_: ServerListQueryInput, _: ServerListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<ServerListQueryInput>> { ): Promise<ChangeCheckResult<ServerListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => change.type === 'app' && change.table === 'servers', (change) => change.type === 'app' && change.table === 'servers'
) )
) { ) {
return { return {

View File

@@ -1,15 +1,15 @@
import { SidebarChatListQueryInput } from '@/operations/queries/sidebar-chat-list'; import { SidebarChatListQueryInput } from '@/operations/queries/sidebar-chat-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { SidebarChatNode } from '@/types/workspaces'; import { SidebarChatNode } from '@/types/workspaces';
import { mapNode } from '@/lib/nodes'; import { mapNode } from '@/main/utils';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
interface UnreadCountRow { interface UnreadCountRow {
@@ -22,7 +22,7 @@ export class SidebarChatListQueryHandler
implements QueryHandler<SidebarChatListQueryInput> implements QueryHandler<SidebarChatListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: SidebarChatListQueryInput, input: SidebarChatListQueryInput
): Promise<QueryResult<SidebarChatListQueryInput>> { ): Promise<QueryResult<SidebarChatListQueryInput>> {
const chats = await this.fetchChats(input); const chats = await this.fetchChats(input);
const collaborators = await this.fetchChatCollaborators(input, chats); const collaborators = await this.fetchChatCollaborators(input, chats);
@@ -33,7 +33,7 @@ export class SidebarChatListQueryHandler
input.userId, input.userId,
chats, chats,
collaborators, collaborators,
unreadCounts, unreadCounts
), ),
state: { state: {
chats, chats,
@@ -46,14 +46,14 @@ export class SidebarChatListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: SidebarChatListQueryInput, input: SidebarChatListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<SidebarChatListQueryInput>> { ): Promise<ChangeCheckResult<SidebarChatListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
(change.table === 'nodes' || change.table === 'user_nodes') && (change.table === 'nodes' || change.table === 'user_nodes') &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -82,7 +82,7 @@ export class SidebarChatListQueryHandler
input.userId, input.userId,
chats, chats,
collaborators, collaborators,
unreadCounts, unreadCounts
), ),
state: { state: {
chats, chats,
@@ -94,10 +94,10 @@ export class SidebarChatListQueryHandler
} }
private async fetchChats( private async fetchChats(
input: SidebarChatListQueryInput, input: SidebarChatListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const chats = await workspaceDatabase const chats = await workspaceDatabase
@@ -111,10 +111,10 @@ export class SidebarChatListQueryHandler
private async fetchChatCollaborators( private async fetchChatCollaborators(
input: SidebarChatListQueryInput, input: SidebarChatListQueryInput,
chats: SelectNode[], chats: SelectNode[]
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const collaboratorIds: string[] = []; const collaboratorIds: string[] = [];
@@ -149,10 +149,10 @@ export class SidebarChatListQueryHandler
private async fetchUnreadCounts( private async fetchUnreadCounts(
input: SidebarChatListQueryInput, input: SidebarChatListQueryInput,
chats: SelectNode[], chats: SelectNode[]
): Promise<UnreadCountRow[]> { ): Promise<UnreadCountRow[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const chatIds = chats.map((chat) => chat.id); const chatIds = chats.map((chat) => chat.id);
@@ -178,7 +178,7 @@ export class SidebarChatListQueryHandler
userId: string, userId: string,
chats: SelectNode[], chats: SelectNode[],
collaborators: SelectNode[], collaborators: SelectNode[],
unreadCounts: UnreadCountRow[], unreadCounts: UnreadCountRow[]
): SidebarChatNode[] => { ): SidebarChatNode[] => {
const sidebarChatNodes: SidebarChatNode[] = []; const sidebarChatNodes: SidebarChatNode[] = [];
@@ -204,7 +204,7 @@ export class SidebarChatListQueryHandler
} }
const collaboratorRow = collaborators.find( const collaboratorRow = collaborators.find(
(r) => r.id === collaboratorId, (r) => r.id === collaboratorId
); );
if (!collaboratorRow) { if (!collaboratorRow) {

View File

@@ -1,17 +1,17 @@
import { SidebarSpaceListQueryInput } from '@/operations/queries/sidebar-space-list'; import { SidebarSpaceListQueryInput } from '@/operations/queries/sidebar-space-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { SidebarNode, SidebarSpaceNode } from '@/types/workspaces'; import { SidebarNode, SidebarSpaceNode } from '@/types/workspaces';
import { mapNode } from '@/lib/nodes'; import { mapNode } from '@/main/utils';
import { Node } from '@/registry'; import { Node } from '@colanode/core';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
import { compareString } from '@/lib/utils'; import { compareString } from '@/lib/utils';
@@ -25,7 +25,7 @@ export class SidebarSpaceListQueryHandler
implements QueryHandler<SidebarSpaceListQueryInput> implements QueryHandler<SidebarSpaceListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: SidebarSpaceListQueryInput, input: SidebarSpaceListQueryInput
): Promise<QueryResult<SidebarSpaceListQueryInput>> { ): Promise<QueryResult<SidebarSpaceListQueryInput>> {
const rows = await this.fetchNodes(input); const rows = await this.fetchNodes(input);
const unreadCounts = await this.fetchUnreadCounts(input, rows); const unreadCounts = await this.fetchUnreadCounts(input, rows);
@@ -42,14 +42,14 @@ export class SidebarSpaceListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: SidebarSpaceListQueryInput, input: SidebarSpaceListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<SidebarSpaceListQueryInput>> { ): Promise<ChangeCheckResult<SidebarSpaceListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
(change.table === 'nodes' || change.table === 'user_nodes') && (change.table === 'nodes' || change.table === 'user_nodes') &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -80,10 +80,10 @@ export class SidebarSpaceListQueryHandler
} }
private async fetchNodes( private async fetchNodes(
input: SidebarSpaceListQueryInput, input: SidebarSpaceListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const query = sql<SelectNode>` const query = sql<SelectNode>`
@@ -108,10 +108,10 @@ export class SidebarSpaceListQueryHandler
private async fetchUnreadCounts( private async fetchUnreadCounts(
input: SidebarSpaceListQueryInput, input: SidebarSpaceListQueryInput,
rows: SelectNode[], rows: SelectNode[]
): Promise<UnreadCountRow[]> { ): Promise<UnreadCountRow[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const channelIds = rows const channelIds = rows
@@ -138,7 +138,7 @@ export class SidebarSpaceListQueryHandler
private buildSidebarSpaceNodes = ( private buildSidebarSpaceNodes = (
rows: SelectNode[], rows: SelectNode[],
unreadCounts: UnreadCountRow[], unreadCounts: UnreadCountRow[]
): SidebarSpaceNode[] => { ): SidebarSpaceNode[] => {
const nodes: Node[] = rows.map(mapNode); const nodes: Node[] = rows.map(mapNode);
const spaces: SidebarSpaceNode[] = []; const spaces: SidebarSpaceNode[] = [];
@@ -164,7 +164,7 @@ export class SidebarSpaceListQueryHandler
private buildSpaceNode = ( private buildSpaceNode = (
node: Node, node: Node,
children: Node[], children: Node[],
unreadCounts: UnreadCountRow[], unreadCounts: UnreadCountRow[]
): SidebarSpaceNode | null => { ): SidebarSpaceNode | null => {
if (node.type !== 'space') { if (node.type !== 'space') {
return null; return null;
@@ -191,7 +191,7 @@ export class SidebarSpaceListQueryHandler
private buildSidearNode = ( private buildSidearNode = (
node: Node, node: Node,
unreadCounts: UnreadCountRow[], unreadCounts: UnreadCountRow[]
): SidebarNode | null => { ): SidebarNode | null => {
const unreadCountRow = unreadCounts.find((r) => r.node_id === node.id); const unreadCountRow = unreadCounts.find((r) => r.node_id === node.id);

View File

@@ -1,22 +1,22 @@
import { UserSearchQueryInput } from '@/operations/queries/user-search'; import { UserSearchQueryInput } from '@/operations/queries/user-search';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import {
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/operations/queries';
import { sql } from 'kysely'; import { sql } from 'kysely';
import { SelectNode } from '@/main/data/workspace/schema'; import { SelectNode } from '@/main/data/workspace/schema';
import { NodeTypes } from '@/lib/constants'; import { NodeTypes } from '@/lib/constants';
import { UserNode } from '@/types/users'; import { UserNode } from '@/types/users';
import { MutationChange } from '@/operations/mutations'; import {
MutationChange,
ChangeCheckResult,
QueryHandler,
QueryResult,
} from '@/main/types';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
export class UserSearchQueryHandler export class UserSearchQueryHandler
implements QueryHandler<UserSearchQueryInput> implements QueryHandler<UserSearchQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: UserSearchQueryInput, input: UserSearchQueryInput
): Promise<QueryResult<UserSearchQueryInput>> { ): Promise<QueryResult<UserSearchQueryInput>> {
const rows = const rows =
input.searchQuery.length > 0 input.searchQuery.length > 0
@@ -33,14 +33,14 @@ export class UserSearchQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: UserSearchQueryInput, input: UserSearchQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<UserSearchQueryInput>> { ): Promise<ChangeCheckResult<UserSearchQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -71,10 +71,10 @@ export class UserSearchQueryHandler
} }
private async searchUsers( private async searchUsers(
input: UserSearchQueryInput, input: UserSearchQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const query = sql<SelectNode>` const query = sql<SelectNode>`
@@ -92,7 +92,7 @@ export class UserSearchQueryHandler
private async fetchUsers(input: UserSearchQueryInput): Promise<SelectNode[]> { private async fetchUsers(input: UserSearchQueryInput): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
return workspaceDatabase return workspaceDatabase

View File

@@ -1,20 +1,20 @@
import { WorkspaceListQueryInput } from '@/operations/queries/workspace-list'; import { WorkspaceListQueryInput } from '@/operations/queries/workspace-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { Workspace, WorkspaceRole } from '@/types/workspaces';
import { SelectWorkspace } from '@/main/data/app/schema';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { Workspace, WorkspaceRole } from '@/types/workspaces';
import { SelectWorkspace } from '@/main/data/app/schema';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
export class WorkspaceListQueryHandler export class WorkspaceListQueryHandler
implements QueryHandler<WorkspaceListQueryInput> implements QueryHandler<WorkspaceListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: WorkspaceListQueryInput, _: WorkspaceListQueryInput
): Promise<QueryResult<WorkspaceListQueryInput>> { ): Promise<QueryResult<WorkspaceListQueryInput>> {
const rows = await this.fetchWorkspaces(); const rows = await this.fetchWorkspaces();
@@ -28,12 +28,12 @@ export class WorkspaceListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: WorkspaceListQueryInput, _: WorkspaceListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<WorkspaceListQueryInput>> { ): Promise<ChangeCheckResult<WorkspaceListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => change.type === 'app' && change.table === 'workspaces', (change) => change.type === 'app' && change.table === 'workspaces'
) )
) { ) {
return { return {
@@ -69,7 +69,7 @@ export class WorkspaceListQueryHandler
databaseManager.appDatabase databaseManager.appDatabase
.selectFrom('accounts') .selectFrom('accounts')
.where('status', '=', 'active') .where('status', '=', 'active')
.select('id'), .select('id')
) )
.execute(); .execute();
} }

View File

@@ -1,22 +1,22 @@
import { WorkspaceUserListQueryInput } from '@/operations/queries/workspace-user-list'; import { WorkspaceUserListQueryInput } from '@/operations/queries/workspace-user-list';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
import { NodeTypes } from '@/lib/constants';
import { mapNode } from '@/main/utils';
import { SelectNode } from '@/main/data/workspace/schema';
import { UserNode } from '@colanode/core';
import { import {
MutationChange,
ChangeCheckResult, ChangeCheckResult,
QueryHandler, QueryHandler,
QueryResult, QueryResult,
} from '@/operations/queries'; } from '@/main/types';
import { NodeTypes } from '@/lib/constants';
import { mapNode } from '@/lib/nodes';
import { SelectNode } from '@/main/data/workspace/schema';
import { UserNode } from '@/registry';
import { MutationChange } from '@/operations/mutations';
import { isEqual } from 'lodash'; import { isEqual } from 'lodash';
export class WorkspaceUserListQueryHandler export class WorkspaceUserListQueryHandler
implements QueryHandler<WorkspaceUserListQueryInput> implements QueryHandler<WorkspaceUserListQueryInput>
{ {
public async handleQuery( public async handleQuery(
input: WorkspaceUserListQueryInput, input: WorkspaceUserListQueryInput
): Promise<QueryResult<WorkspaceUserListQueryInput>> { ): Promise<QueryResult<WorkspaceUserListQueryInput>> {
const rows = await this.fetchNodes(input); const rows = await this.fetchNodes(input);
return { return {
@@ -30,14 +30,14 @@ export class WorkspaceUserListQueryHandler
public async checkForChanges( public async checkForChanges(
changes: MutationChange[], changes: MutationChange[],
input: WorkspaceUserListQueryInput, input: WorkspaceUserListQueryInput,
state: Record<string, any>, state: Record<string, any>
): Promise<ChangeCheckResult<WorkspaceUserListQueryInput>> { ): Promise<ChangeCheckResult<WorkspaceUserListQueryInput>> {
if ( if (
!changes.some( !changes.some(
(change) => (change) =>
change.type === 'workspace' && change.type === 'workspace' &&
change.table === 'nodes' && change.table === 'nodes' &&
change.userId === input.userId, change.userId === input.userId
) )
) { ) {
return { return {
@@ -64,10 +64,10 @@ export class WorkspaceUserListQueryHandler
} }
private async fetchNodes( private async fetchNodes(
input: WorkspaceUserListQueryInput, input: WorkspaceUserListQueryInput
): Promise<SelectNode[]> { ): Promise<SelectNode[]> {
const workspaceDatabase = await databaseManager.getWorkspaceDatabase( const workspaceDatabase = await databaseManager.getWorkspaceDatabase(
input.userId, input.userId
); );
const offset = input.page * input.count; const offset = input.page * input.count;

View File

@@ -1,16 +1,8 @@
import { import { MutationInput, MutationMap } from '@/operations/mutations';
MutationChange, import { MutationChange, MutationHandler } from '@/main/types';
MutationHandler,
MutationInput,
MutationMap,
} from '@/operations/mutations';
import { mutationHandlerMap } from '@/main/handlers/mutations'; import { mutationHandlerMap } from '@/main/handlers/mutations';
import { import { QueryInput, QueryMap } from '@/operations/queries';
QueryHandler, import { QueryHandler, SubscribedQuery } from '@/main/types';
QueryInput,
QueryMap,
SubscribedQuery,
} from '@/operations/queries';
import { queryHandlerMap } from '@/main/handlers/queries'; import { queryHandlerMap } from '@/main/handlers/queries';
import { eventBus } from '@/lib/event-bus'; import { eventBus } from '@/lib/event-bus';
import { import {
@@ -25,7 +17,7 @@ class Mediator {
new Map(); new Map();
public async executeMutation<T extends MutationInput>( public async executeMutation<T extends MutationInput>(
input: T, input: T
): Promise<MutationMap[T['type']]['output']> { ): Promise<MutationMap[T['type']]['output']> {
const handler = mutationHandlerMap[ const handler = mutationHandlerMap[
input.type input.type
@@ -40,7 +32,7 @@ class Mediator {
} }
public async executeQuery<T extends QueryInput>( public async executeQuery<T extends QueryInput>(
input: T, input: T
): Promise<QueryMap[T['type']]['output']> { ): Promise<QueryMap[T['type']]['output']> {
const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>; const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>;
const result = await handler.handleQuery(input); const result = await handler.handleQuery(input);
@@ -49,7 +41,7 @@ class Mediator {
public async executeQueryAndSubscribe<T extends QueryInput>( public async executeQueryAndSubscribe<T extends QueryInput>(
id: string, id: string,
input: T, input: T
): Promise<QueryMap[T['type']]['output']> { ): Promise<QueryMap[T['type']]['output']> {
const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>; const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>;
const result = await handler.handleQuery(input); const result = await handler.handleQuery(input);
@@ -62,7 +54,7 @@ class Mediator {
public async executeMessage<T extends MessageInput>( public async executeMessage<T extends MessageInput>(
context: MessageContext, context: MessageContext,
input: T, input: T
): Promise<void> { ): Promise<void> {
const handler = messageHandlerMap[input.type] as MessageHandler<T>; const handler = messageHandlerMap[input.type] as MessageHandler<T>;
await handler.handleMessage(context, input); await handler.handleMessage(context, input);
@@ -85,7 +77,7 @@ class Mediator {
const changeCheckResult = await handler.checkForChanges( const changeCheckResult = await handler.checkForChanges(
changes, changes,
query.input, query.input,
query.result.state, query.result.state
); );
if (changeCheckResult.hasChanges && changeCheckResult.result) { if (changeCheckResult.hasChanges && changeCheckResult.result) {
const newResult = changeCheckResult.result; const newResult = changeCheckResult.result;

View File

@@ -1,12 +1,10 @@
import * as Y from 'yjs'; import * as Y from 'yjs';
import { NodeAttributes } from '@/registry'; import { NodeAttributes, registry, applyCrdt } from '@colanode/core';
import { fromUint8Array, toUint8Array } from 'js-base64'; import { fromUint8Array, toUint8Array } from 'js-base64';
import { applyCrdt } from '@/main/crdt';
import { import {
LocalCreateNodeChangeData, LocalCreateNodeChangeData,
LocalUpdateNodeChangeData, LocalUpdateNodeChangeData,
} from '@/types/sync'; } from '@/types/sync';
import { registry } from '@/registry';
import { generateId } from '@/lib/id'; import { generateId } from '@/lib/id';
import { IdType } from '@/lib/id'; import { IdType } from '@/lib/id';
import { databaseManager } from '@/main/data/database-manager'; import { databaseManager } from '@/main/data/database-manager';
@@ -19,7 +17,7 @@ class NodeManager {
transaction: Transaction<WorkspaceDatabaseSchema>, transaction: Transaction<WorkspaceDatabaseSchema>,
userId: string, userId: string,
id: string, id: string,
attributes: NodeAttributes, attributes: NodeAttributes
) { ) {
const doc = new Y.Doc({ const doc = new Y.Doc({
guid: id, guid: id,
@@ -75,7 +73,7 @@ class NodeManager {
async updateNode( async updateNode(
userId: string, userId: string,
id: string, id: string,
updater: (attributes: NodeAttributes) => NodeAttributes, updater: (attributes: NodeAttributes) => NodeAttributes
) { ) {
const workspaceDatabase = const workspaceDatabase =
await databaseManager.getWorkspaceDatabase(userId); await databaseManager.getWorkspaceDatabase(userId);
@@ -113,7 +111,7 @@ class NodeManager {
applyCrdt( applyCrdt(
registry[updatedAttributes.type].schema, registry[updatedAttributes.type].schema,
updatedAttributes, updatedAttributes,
attributesMap, attributesMap
); );
}); });
@@ -165,10 +163,10 @@ class NodeManager {
return hasChanges; return hasChanges;
}); });
if (result) { return result;
return true;
}
} }
throw new Error('Failed to update node');
} }
} }

View File

@@ -1,9 +1,15 @@
import { WebSocket } from 'ws'; import { WebSocket } from 'ws';
import { buildSynapseUrl } from '@/lib/servers';
import { BackoffCalculator } from '@/lib/backoff-calculator'; import { BackoffCalculator } from '@/lib/backoff-calculator';
import { MessageContext, MessageInput } from '@/operations/messages'; import { MessageContext, MessageInput } from '@/operations/messages';
import { mediator } from '@/main/mediator'; import { mediator } from '@/main/mediator';
import { SelectAccount, SelectServer } from '@/main/data/app/schema'; import { SelectAccount, SelectServer } from '@/main/data/app/schema';
import { ServerAttributes } from '@/types/servers';
const buildSynapseUrl = (server: SelectServer, deviceId: string) => {
const attributes = JSON.parse(server.attributes) as ServerAttributes;
const protocol = attributes?.insecure ? 'ws' : 'wss';
return `${protocol}://${server.domain}/v1/synapse?device_id=${deviceId}`;
};
export class SocketConnection { export class SocketConnection {
private readonly server: SelectServer; private readonly server: SelectServer;
@@ -35,7 +41,7 @@ export class SocketConnection {
headers: { headers: {
authorization: this.account.token, authorization: this.account.token,
}, },
}, }
); );
this.socket.onmessage = async (event) => { this.socket.onmessage = async (event) => {

View File

@@ -0,0 +1,50 @@
import { AppDatabaseSchema } from '@/main/data/app/schema';
import { WorkspaceDatabaseSchema } from '@/main/data/workspace/schema';
import { MutationInput, MutationMap } from '@/operations/mutations';
import { QueryInput, QueryMap } from '@/operations/queries';
export interface MutationHandler<T extends MutationInput> {
handleMutation: (input: T) => Promise<MutationResult<T>>;
}
export type MutationResult<T extends MutationInput> = {
output: MutationMap[T['type']]['output'];
changes?: MutationChange[];
};
export type MutationChange = AppMutationChange | WorkspaceMutationChange;
export type AppMutationChange = {
type: 'app';
table: keyof AppDatabaseSchema;
};
export type WorkspaceMutationChange = {
type: 'workspace';
table: keyof WorkspaceDatabaseSchema;
userId: string;
};
export interface QueryHandler<T extends QueryInput> {
handleQuery: (input: T) => Promise<QueryResult<T>>;
checkForChanges: (
changes: MutationChange[],
input: T,
state: Record<string, any>
) => Promise<ChangeCheckResult<T>>;
}
export type QueryResult<T extends QueryInput> = {
output: QueryMap[T['type']]['output'];
state: Record<string, any>;
};
export type SubscribedQuery<T extends QueryInput> = {
input: T;
result: QueryResult<T>;
};
export type ChangeCheckResult<T extends QueryInput> = {
hasChanges: boolean;
result?: QueryResult<T>;
};

View File

@@ -1,6 +1,8 @@
import { app } from 'electron'; import { app } from 'electron';
import { DeleteResult, InsertResult, UpdateResult } from 'kysely'; import { DeleteResult, InsertResult, UpdateResult } from 'kysely';
import path from 'path'; import path from 'path';
import { SelectNode } from '@/main/data/workspace/schema';
import { Node } from '@colanode/core';
export const appPath = app.getPath('userData'); export const appPath = app.getPath('userData');
@@ -24,7 +26,7 @@ export const hasInsertChanges = (result: InsertResult[]): boolean => {
} }
return result.some( return result.some(
(r) => r.numInsertedOrUpdatedRows && r.numInsertedOrUpdatedRows > 0n, (r) => r.numInsertedOrUpdatedRows && r.numInsertedOrUpdatedRows > 0n
); );
}; };
@@ -39,3 +41,21 @@ export const hasUpdateChanges = (result: UpdateResult[]): boolean => {
export const hasDeleteChanges = (result: DeleteResult[]): boolean => { export const hasDeleteChanges = (result: DeleteResult[]): boolean => {
return result.some((r) => r.numDeletedRows && r.numDeletedRows > 0n); return result.some((r) => r.numDeletedRows && r.numDeletedRows > 0n);
}; };
export const mapNode = (row: SelectNode): Node => {
return {
id: row.id,
type: row.type as any,
index: row.index,
parentId: row.parent_id,
attributes: JSON.parse(row.attributes),
createdAt: row.created_at,
createdBy: row.created_by,
updatedAt: row.updated_at,
updatedBy: row.updated_by,
versionId: row.version_id,
serverCreatedAt: row.server_created_at,
serverUpdatedAt: row.server_updated_at,
serverVersionId: row.server_version_id,
};
};

View File

@@ -1,4 +1,4 @@
import { FieldType } from '@/registry'; import { FieldType } from '@colanode/core';
export type FieldCreateMutationInput = { export type FieldCreateMutationInput = {
type: 'field_create'; type: 'field_create';

View File

@@ -1,28 +1,3 @@
import { AppDatabaseSchema } from '@/main/data/app/schema';
import { WorkspaceDatabaseSchema } from '@/main/data/workspace/schema';
export interface MutationMap {} export interface MutationMap {}
export type MutationInput = MutationMap[keyof MutationMap]['input']; export type MutationInput = MutationMap[keyof MutationMap]['input'];
export interface MutationHandler<T extends MutationInput> {
handleMutation: (input: T) => Promise<MutationResult<T>>;
}
export type MutationResult<T extends MutationInput> = {
output: MutationMap[T['type']]['output'];
changes?: MutationChange[];
};
export type MutationChange = AppMutationChange | WorkspaceMutationChange;
export type AppMutationChange = {
type: 'app';
table: keyof AppDatabaseSchema;
};
export type WorkspaceMutationChange = {
type: 'workspace';
table: keyof WorkspaceDatabaseSchema;
userId: string;
};

View File

@@ -1,4 +1,4 @@
import { ViewAttributes } from '@/registry'; import { ViewAttributes } from '@colanode/core';
export type ViewUpdateMutationInput = { export type ViewUpdateMutationInput = {
type: 'view_update'; type: 'view_update';

View File

@@ -1,29 +1,3 @@
import { MutationChange } from '@/operations/mutations';
export interface QueryMap {} export interface QueryMap {}
export type QueryInput = QueryMap[keyof QueryMap]['input']; export type QueryInput = QueryMap[keyof QueryMap]['input'];
export interface QueryHandler<T extends QueryInput> {
handleQuery: (input: T) => Promise<QueryResult<T>>;
checkForChanges: (
changes: MutationChange[],
input: T,
state: Record<string, any>
) => Promise<ChangeCheckResult<T>>;
}
export type QueryResult<T extends QueryInput> = {
output: QueryMap[T['type']]['output'];
state: Record<string, any>;
};
export type SubscribedQuery<T extends QueryInput> = {
input: T;
result: QueryResult<T>;
};
export type ChangeCheckResult<T extends QueryInput> = {
hasChanges: boolean;
result?: QueryResult<T>;
};

View File

@@ -1,4 +1,4 @@
import { Node } from '@/registry'; import { Node } from '@colanode/core';
export type NodeGetQueryInput = { export type NodeGetQueryInput = {
type: 'node_get'; type: 'node_get';

View File

@@ -1,5 +1,8 @@
import { RecordNode } from '@/registry'; import {
import { ViewFilterAttributes, ViewSortAttributes } from '@/registry'; RecordNode,
ViewFilterAttributes,
ViewSortAttributes,
} from '@colanode/core';
export type RecordListQueryInput = { export type RecordListQueryInput = {
type: 'record_list'; type: 'record_list';

View File

@@ -1,4 +1,4 @@
import { UserNode } from '@/registry'; import { UserNode } from '@colanode/core';
export type WorkspaceUserListQueryInput = { export type WorkspaceUserListQueryInput = {
type: 'workspace_user_list'; type: 'workspace_user_list';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Spinner } from '@/renderer/components/ui/spinner'; import { Spinner } from '@/renderer/components/ui/spinner';
export const AppLoading = () => { export const AppLoading = () => {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
AlertDialog, AlertDialog,
AlertDialogCancel, AlertDialogCancel,

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@@ -23,7 +22,6 @@ interface AccountSettingsDialogProps {
} }
export const AccountSettingsDialog = ({ export const AccountSettingsDialog = ({
id,
open, open,
onOpenChange, onOpenChange,
}: AccountSettingsDialogProps) => { }: AccountSettingsDialogProps) => {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Input } from '@/renderer/components/ui/input'; import { Input } from '@/renderer/components/ui/input';
import { Button } from '@/renderer/components/ui/button'; import { Button } from '@/renderer/components/ui/button';
import { Spinner } from '@/renderer/components/ui/spinner'; import { Spinner } from '@/renderer/components/ui/spinner';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Input } from '@/renderer/components/ui/input'; import { Input } from '@/renderer/components/ui/input';
import { Button } from '@/renderer/components/ui/button'; import { Button } from '@/renderer/components/ui/button';
import { Spinner } from '@/renderer/components/ui/spinner'; import { Spinner } from '@/renderer/components/ui/spinner';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { LoginForm } from '@/renderer/components/accounts/login-form'; import { LoginForm } from '@/renderer/components/accounts/login-form';
import { useQuery } from '@/renderer/hooks/use-query'; import { useQuery } from '@/renderer/hooks/use-query';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
Tabs, Tabs,
TabsContent, TabsContent,

View File

@@ -16,7 +16,7 @@ export const AvatarUpload = ({ onUpload }: AvatarUploadProps) => {
const [isFileDialogOpen, setIsFileDialogOpen] = React.useState(false); const [isFileDialogOpen, setIsFileDialogOpen] = React.useState(false);
const [url, setUrl] = React.useState<string | undefined>(undefined); const [url, setUrl] = React.useState<string | undefined>(undefined);
const handleSubmit = async (url: string) => { const handleSubmit = async (_: string) => {
// TODO // TODO
}; };

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { import {
getAvatarSizeClasses, getAvatarSizeClasses,
@@ -57,7 +56,7 @@ const AvatarFallback = ({ id, name, size, className }: AvatarProps) => {
className={cn( className={cn(
'inline-flex items-center justify-center overflow-hidden rounded text-white shadow', 'inline-flex items-center justify-center overflow-hidden rounded text-white shadow',
getAvatarSizeClasses(size), getAvatarSizeClasses(size),
className, className
)} )}
style={{ backgroundColor: color }} style={{ backgroundColor: color }}
> >

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Conversation } from '@/renderer/components/messages/conversation'; import { Conversation } from '@/renderer/components/messages/conversation';
interface ChannelContainerProps { interface ChannelContainerProps {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { useWorkspace } from '@/renderer/contexts/workspace'; import { useWorkspace } from '@/renderer/contexts/workspace';
import { import {
Dialog, Dialog,

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
AlertDialog, AlertDialog,
AlertDialogCancel, AlertDialogCancel,

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { Conversation } from '@/renderer/components/messages/conversation'; import { Conversation } from '@/renderer/components/messages/conversation';
interface ChatContainerProps { interface ChatContainerProps {

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { NodeCollaborator as NodeCollaboratorType } from '@/types/nodes'; import { NodeCollaborator as NodeCollaboratorType } from '@/types/nodes';
import { Avatar } from '@/renderer/components/avatars/avatar'; import { Avatar } from '@/renderer/components/avatars/avatar';
import { NodeCollaboratorRoleDropdown } from '@/renderer/components/collaborators/node-collaborator-role-dropdown'; import { NodeCollaboratorRoleDropdown } from '@/renderer/components/collaborators/node-collaborator-role-dropdown';

View File

@@ -1,4 +1,3 @@
import React from 'react';
import { import {
Popover, Popover,
PopoverTrigger, PopoverTrigger,

View File

@@ -1,8 +1,11 @@
import React from 'react'; import React from 'react';
import { useWorkspace } from '@/renderer/contexts/workspace'; import { useWorkspace } from '@/renderer/contexts/workspace';
import { useMutation } from '@/renderer/hooks/use-mutation'; import { useMutation } from '@/renderer/hooks/use-mutation';
import { RecordNode } from '@/registry'; import {
import { SelectFieldAttributes, SelectOptionAttributes } from '@/registry'; RecordNode,
SelectFieldAttributes,
SelectOptionAttributes,
} from '@colanode/core';
import { useDrag } from 'react-dnd'; import { useDrag } from 'react-dnd';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
@@ -22,7 +25,7 @@ export const BoardViewCard = ({ record }: BoardViewCardProps) => {
const [, drag] = useDrag({ const [, drag] = useDrag({
type: 'board-record', type: 'board-record',
item: { id: record.id }, item: { id: record.id },
end: (item, monitor) => { end: (_, monitor) => {
const dropResult = monitor.getDropResult<DragResult>(); const dropResult = monitor.getDropResult<DragResult>();
if (dropResult != null) { if (dropResult != null) {
if (isPending) return; if (isPending) return;
@@ -64,7 +67,7 @@ export const BoardViewCard = ({ record }: BoardViewCardProps) => {
key={record.id} key={record.id}
className={cn( className={cn(
'animate-fade-in flex cursor-pointer flex-col gap-1 rounded-md border p-2 text-left hover:bg-gray-50', 'animate-fade-in flex cursor-pointer flex-col gap-1 rounded-md border p-2 text-left hover:bg-gray-50',
hasName ? '' : 'text-muted-foreground', hasName ? '' : 'text-muted-foreground'
)} )}
onClick={() => workspace.openModal(record.id)} onClick={() => workspace.openModal(record.id)}
> >

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { SelectOptionBadge } from '@/renderer/components/databases/fields/select-option-badge'; import { SelectOptionBadge } from '@/renderer/components/databases/fields/select-option-badge';
import { SelectOptionAttributes } from '@/registry'; import { SelectOptionAttributes } from '@colanode/core';
interface BoardViewColumnHeaderProps { interface BoardViewColumnHeaderProps {
option: SelectOptionAttributes; option: SelectOptionAttributes;

View File

@@ -1,11 +1,10 @@
import React from 'react';
import { useDatabase } from '@/renderer/contexts/database'; import { useDatabase } from '@/renderer/contexts/database';
import { useInfiniteQuery } from '@/renderer/hooks/use-infinite-query'; import { useInfiniteQuery } from '@/renderer/hooks/use-infinite-query';
import { import {
SelectFieldAttributes, SelectFieldAttributes,
SelectOptionAttributes, SelectOptionAttributes,
ViewFilterAttributes, ViewFilterAttributes,
} from '@/registry'; } from '@colanode/core';
import { BoardViewCard } from '@/renderer/components/databases/boards/board-view-card'; import { BoardViewCard } from '@/renderer/components/databases/boards/board-view-card';
import { useWorkspace } from '@/renderer/contexts/workspace'; import { useWorkspace } from '@/renderer/contexts/workspace';
import { useView } from '@/renderer/contexts/view'; import { useView } from '@/renderer/contexts/view';
@@ -35,8 +34,7 @@ export const BoardViewColumnRecords = ({
value: [option.id], value: [option.id],
}, },
]; ];
const { data, isPending, isFetchingNextPage, fetchNextPage, hasNextPage } = const { data } = useInfiniteQuery({
useInfiniteQuery({
initialPageInput: { initialPageInput: {
type: 'record_list', type: 'record_list',
databaseId: database.id, databaseId: database.id,

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { getSelectOptionLightColorClass } from '@/lib/databases'; import { getSelectOptionLightColorClass } from '@/lib/databases';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { useDrop } from 'react-dnd'; import { useDrop } from 'react-dnd';
import { SelectFieldAttributes, SelectOptionAttributes } from '@/registry'; import { SelectFieldAttributes, SelectOptionAttributes } from '@colanode/core';
import { BoardViewColumnHeader } from '@/renderer/components/databases/boards/board-view-column-header'; import { BoardViewColumnHeader } from '@/renderer/components/databases/boards/board-view-column-header';
import { BoardViewColumnRecords } from '@/renderer/components/databases/boards/board-view-column-records'; import { BoardViewColumnRecords } from '@/renderer/components/databases/boards/board-view-column-records';

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { useWorkspace } from '@/renderer/contexts/workspace'; import { useWorkspace } from '@/renderer/contexts/workspace';
import { RecordNode } from '@/registry'; import { RecordNode } from '@colanode/core';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
interface CalendarViewCardProps { interface CalendarViewCardProps {
@@ -19,7 +18,7 @@ export const CalendarViewCard = ({ record }: CalendarViewCardProps) => {
key={record.id} key={record.id}
className={cn( className={cn(
'animate-fade-in flex cursor-pointer flex-col gap-1 rounded-md border p-2 hover:bg-gray-50', 'animate-fade-in flex cursor-pointer flex-col gap-1 rounded-md border p-2 hover:bg-gray-50',
hasName ? '' : 'text-muted-foreground', hasName ? '' : 'text-muted-foreground'
)} )}
onClick={() => workspace.openModal(record.id)} onClick={() => workspace.openModal(record.id)}
> >

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { cn, isSameDay } from '@/lib/utils'; import { cn, isSameDay } from '@/lib/utils';
import { RecordNode } from '@/registry'; import { RecordNode } from '@colanode/core';
import { CalendarViewCard } from '@/renderer/components/databases/calendars/calendar-view-card'; import { CalendarViewCard } from '@/renderer/components/databases/calendars/calendar-view-card';
import { Plus } from 'lucide-react'; import { Plus } from 'lucide-react';
@@ -27,13 +26,13 @@ export const CalendarViewDay = ({
<div <div
className={cn( className={cn(
'flex justify-between text-sm', 'flex justify-between text-sm',
isOutside ? 'text-muted-foreground' : '', isOutside ? 'text-muted-foreground' : ''
)} )}
> >
<Plus <Plus
className={cn( className={cn(
'size-4 cursor-pointer opacity-0', 'size-4 cursor-pointer opacity-0',
canCreateRecord ? 'group-hover:opacity-100' : '', canCreateRecord ? 'group-hover:opacity-100' : ''
)} )}
onClick={() => {}} onClick={() => {}}
/> />

Some files were not shown because too many files have changed in this diff Show More