Skip to content

Commit

Permalink
Added memory database for resources tests
Browse files Browse the repository at this point in the history
* Minor refactoring
  • Loading branch information
GuilhermeF03 committed May 11, 2024
1 parent 6b1db05 commit 88bbdc8
Show file tree
Hide file tree
Showing 26 changed files with 248 additions and 85 deletions.
2 changes: 1 addition & 1 deletion code/server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 'latest'
services:
postgres-db:
container_name: postgres-db
container_name: notespace-postgres-db
build:
context: .
dockerfile: docker/Dockerfile-db
Expand Down
2 changes: 1 addition & 1 deletion code/server/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
/*Controllers*/
'@controllers/*': ['./src/ts/controllers/*'],
/*Databases*/
'@database/*': ['./src/ts/database/*'],
'@databases/*': ['./src/ts/databases/*'],
/*Others*/
'@src/*': ['./src/ts/*'],
'@domain/*': ['./src/ts/domain/*'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function resourcesHandlers(service: ResourcesService, io: Server) {
httpResponse.noContent(res).send();
};

const router = PromiseRouter();
const router = PromiseRouter({mergeParams: true});
router.post('/', createResource);
router.get('/:id', getResource);
router.put('/:id', updateResource);
Expand Down
4 changes: 2 additions & 2 deletions code/server/src/ts/controllers/ws/events.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { SocketHandler } from '@controllers/ws/types';
import { DocumentService } from '@services/DocumentService';
import { DocumentsService } from '@services/DocumentsService';
import onOperation from '@controllers/ws/namespaces/document/onOperation';
import onCursorChange from '@controllers/ws/namespaces/document/onCursorChange';
import onJoinDocument from '@controllers/ws/namespaces/document/onJoinDocument';
import onLeaveDocument from '@controllers/ws/namespaces/document/onLeaveDocument';
import onJoinWorkspace from '@controllers/ws/namespaces/workspace/onJoinWorkspace';
import onLeaveWorkspace from '@controllers/ws/namespaces/workspace/onLeaveWorkspace';

export default function events(service: DocumentService): Record<string, Record<string, SocketHandler>> {
export default function events(service: DocumentsService): Record<string, Record<string, SocketHandler>> {
if (!service) throw new Error('Service parameter is required');

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { Socket } from 'socket.io';
import { Operation } from '@notespace/shared/src/document/types/operations';

import { ForbiddenError, InvalidParameterError } from '@domain/errors/errors';
import { DocumentService } from '@services/DocumentService';
import { DocumentsService } from '@services/DocumentsService';
import rooms from '@controllers/ws/rooms/rooms';

function onOperation(service: DocumentService) {
function onOperation(service: DocumentsService) {
return async (socket: Socket, operations: Operation[]) => {
if (!operations) throw new InvalidParameterError('Operations are required');

const documentId = rooms.document.get(socket)?.id;
if (!documentId) throw new ForbiddenError('Client socket not in a room');

socket.broadcast.to(documentId).emit('operation', operations);
await service.addOperations('documents', documentId, operations);
await service.updateDocument('documents', documentId, operations);
socket.emit('ack');
};
}
Expand Down
15 changes: 0 additions & 15 deletions code/server/src/ts/database/Databases.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { NotFoundError } from '@domain/errors/errors';
import { Operation } from '@notespace/shared/src/document/types/operations';
import { DocumentRepository } from '@database/types';
import { DocumentsRepository } from '@databases/types';
import { DocumentContent } from '@notespace/shared/src/workspace/types/document';

export class MemoryDocumentDatabase implements DocumentRepository {
export class MemoryDocumentsDB implements DocumentsRepository {
private readonly documents: Record<string, Record<string, DocumentContent>> = {};

async createDocument(wid: string, id: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { firestore } from 'firebase-admin';
import FieldValue = firestore.FieldValue;
import { DocumentRepository } from '@database/types';
import CollectionReference = firestore.CollectionReference;
import db from '@database/firestore/config';
import db from '@database/documents/firestore/config';

export class FirestoreDocumentDatabase implements DocumentRepository {
export class FirestoreDocumentsDB implements DocumentRepository {
async createDocument(wid: string, id: string) {
const documents = await this.getWorkspace(wid);
const docData: DocumentContent = { operations: [] };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cert, initializeApp, ServiceAccount } from 'firebase-admin/app';
import serviceAccount from '@/firestore-key-5cddf-472039f8dbb6.json';
import serviceAccount from './firestore-key-5cddf-472039f8dbb6.json';
import { getFirestore } from 'firebase-admin/firestore';

initializeApp({
Expand Down
15 changes: 15 additions & 0 deletions code/server/src/ts/databases/resources/memory/MemoryDB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { DocumentsRepository, NoteSpaceDatabase, ResourcesRepository, WorkspacesRepository } from '@databases/types';
import { MemoryResourcesDB } from '@databases/resources/memory/MemoryResourcesDB';
import { MemoryWorkspacesDB } from '@databases/resources/memory/MemoryWorkspacesDB';

export class MemoryDB implements NoteSpaceDatabase {
readonly document: DocumentsRepository;
readonly resource: ResourcesRepository;
readonly workspace: WorkspacesRepository;

constructor(document: DocumentsRepository) {
this.document = document;
this.resource = new MemoryResourcesDB();
this.workspace = new MemoryWorkspacesDB();
}
}
18 changes: 18 additions & 0 deletions code/server/src/ts/databases/resources/memory/MemoryResourcesDB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ResourcesRepository } from '@databases/types';
import { ResourceType, WorkspaceResource } from '@notespace/shared/src/workspace/types/resource';
import {memoryDB} from '@databases/resources/memory/utils';

export class MemoryResourcesDB implements ResourcesRepository {
createResource(wid: string, name: string, type: ResourceType, parent?: string | undefined) : Promise<string> {
return Promise.resolve(memoryDB.addWorkspaceResource(wid, name));
}
getResource(id: string): Promise<WorkspaceResource> {
return Promise.resolve(memoryDB.getWorkspaceResource(id));
}
updateResource(id: string, newProps: Partial<WorkspaceResource>): Promise<void> {
return Promise.resolve(memoryDB.updateWorkspaceResource(id, newProps));
}
deleteResource(id: string): Promise<void> {
return Promise.resolve(memoryDB.removeWorkspaceResource(id));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { WorkspacesRepository } from '@databases/types';
import { WorkspaceMetaData } from '@notespace/shared/src/workspace/types/workspace';
import { memoryDB } from '@databases/resources/memory/utils';
import { WorkspaceResource } from '@notespace/shared/src/workspace/types/resource';


export class MemoryWorkspacesDB implements WorkspacesRepository {
getWorkspaceResources(id: string):Promise<WorkspaceResource[]>{
return memoryDB.getWorkspaceResources(id);
}
createWorkspace(name: string): Promise<string> {
return memoryDB.createWorkspace(name);
}
getWorkspaces(): Promise<WorkspaceMetaData[]> {
return memoryDB.getWorkspaces();
}
getWorkspace(id: string): Promise<WorkspaceMetaData> {
return memoryDB.getWorkspace(id);
}
updateWorkspace(id: string, name: string): Promise<void> {
return memoryDB.updateWorkspace(id, name);
}
deleteWorkspace(id: string): Promise<void> {
return memoryDB.deleteWorkspace(id);
}
}
94 changes: 94 additions & 0 deletions code/server/src/ts/databases/resources/memory/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { ResourceType, WorkspaceResource } from '@notespace/shared/src/workspace/types/resource';

type Workspace = {
id: string;
name: string;
resources: string[];
}

const workspaces = new Map<string, Workspace>();

export const createWorkspace = async (name: string): Promise<string> => {
const id = Math.random().toString(36).substring(7);
workspaces.set(id, { id, name, resources: [] });
return id;
}

export const getWorkspaces = async (): Promise<Workspace[]> => {
return Array.from(workspaces.values());
}

export const getWorkspace = async (id: string): Promise<Workspace> => {
const workspace = workspaces.get(id);
if (!workspace) throw new Error(`Workspace with id ${id} not found`);
return workspace;
}

export const updateWorkspace = async (id: string, name: string): Promise<void> => {
const workspace = workspaces.get(id);
if (!workspace) throw new Error(`Workspace with id ${id} not found`);
workspaces.set(id, { ...workspace, name });
}

export const deleteWorkspace = async (id: string): Promise<void> => {
if (!workspaces.delete(id)) throw new Error(`Workspace with id ${id} not found`);
}

export const getWorkspaceResources = async (id: string): Promise<WorkspaceResource[]> => {
const workspace = workspaces.get(id);
if (!workspace) throw new Error(`Workspace with id ${id} not found`);
return workspace.resources.map(id => ({ id,
name: 'Resource',
workspace: id,
type: ResourceType.DOCUMENT,
parent: id,
children: [],
}));
}

export const getWorkspaceResource = async (resourceId: string): Promise<WorkspaceResource> => {
const workspace = Array.from(workspaces.values()).find(w => w.resources.includes(resourceId));
if (!workspace) throw new Error(`Resource with id ${resourceId} not found`);
return {
id: resourceId,
name: 'Resource',
workspace: workspace.id,
type: ResourceType.DOCUMENT,
parent: workspace.id,
children: [],
};
}

export const addWorkspaceResource = async (wid: string, resourceId: string): Promise<string> => {
const workspace = workspaces.get(wid);
if (!workspace) throw new Error(`Workspace with id ${wid} not found`);
workspace.resources.push(resourceId);
return Promise.resolve(resourceId);
}

export const updateWorkspaceResource = async (resourceId: string, newProps: Partial<WorkspaceResource>): Promise<void> => {
const workspace = Array.from(workspaces.values()).find(w => w.resources.includes(resourceId));
if (!workspace) throw new Error(`Resource with id ${resourceId} not found`);
const resource = workspace.resources.find(id => id === resourceId);
if (!resource) throw new Error(`Resource with id ${resourceId} not found`);
Object.assign(resource, newProps);
}

export const removeWorkspaceResource = async ( resourceId: string): Promise<void> => {
const workspace = Array.from(workspaces.values()).find(w => w.resources.includes(resourceId));
if (!workspace) throw new Error(`Resource with id ${resourceId} not found`);
workspace.resources = workspace.resources.filter(id => id !== resourceId);
}

export const memoryDB = {
createWorkspace,
getWorkspaces,
getWorkspace,
updateWorkspace,
deleteWorkspace,
getWorkspaceResources,
getWorkspaceResource,
addWorkspaceResource,
updateWorkspaceResource,
removeWorkspaceResource,
};
15 changes: 15 additions & 0 deletions code/server/src/ts/databases/resources/postgres/PSQLDB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { PSQLResourcesDB } from '@databases/resources/postgres/PSQLResourcesDB';
import { PSQLWorkspacesDB } from '@databases/resources/postgres/PSQLWorkspacesDB';
import { DocumentsRepository, NoteSpaceDatabase, ResourcesRepository, WorkspacesRepository } from '@databases/types';

export class PSQLDB implements NoteSpaceDatabase{
readonly document: DocumentsRepository;
readonly resource: ResourcesRepository;
readonly workspace: WorkspacesRepository;

constructor(document: DocumentsRepository) {
this.document = document;
this.resource = new PSQLResourcesDB();
this.workspace = new PSQLWorkspacesDB();
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { ResourceType, WorkspaceResource } from '@notespace/shared/src/workspace/types/resource';
import { ResourceRepository } from '@database/types';
import { ResourcesRepository } from '@databases/types';
import { InvalidParameterError, NotFoundError } from '@domain/errors/errors';
import sql from '@database/postgres/config';
import sql from '@databases/resources/postgres/config';
import { isEmpty } from 'lodash';

export class PSQLResourcesDB implements ResourcesRepository {

export class PostgresResourceDatabase implements ResourceRepository {
async createResource(wid: string, name: string, type: ResourceType, parent?: string): Promise<string> {
const resource = { workspace: wid, name, type, parent: parent || 'IDKYET' };
const resource = { workspace: wid, name, type, parent: parent };
const results = await sql`
INSERT INTO resource ${sql(resource)}
RETURNING id
`;
if (results.length === 0) throw new Error('Resource not created');
if (isEmpty(results)) throw new Error('Resource not created');
return results[0].id;
}

async getResource(id: string): Promise<WorkspaceResource> {
const results: WorkspaceResource[] = await sql`
SELECT * FROM resource WHERE id = ${id}
`;
if (results.length === 0) throw new NotFoundError('Resource not found');
if (isEmpty(results)) throw new NotFoundError('Resource not found');
return results[0];
}

Expand All @@ -29,14 +31,14 @@ export class PostgresResourceDatabase implements ResourceRepository {
SET ${sql(resource)}
WHERE id = ${id}
`;
if (results.length === 0) throw new Error('Resource not updated');
if (isEmpty(results)) throw new Error('Resource not updated');
}

async deleteResource(id: string) {
const results = await sql`
DELETE FROM resource
WHERE id = ${id}
`;
if (results.length === 0) throw new Error('Resource not deleted');
if (isEmpty(results)) throw new Error('Resource not deleted');
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { WorkspaceResource } from '@notespace/shared/src/workspace/types/resource';
import { WorkspaceMetaData } from '@notespace/shared/src/workspace/types/workspace';
import { NotFoundError } from '@domain/errors/errors';
import sql from '@database/postgres/config';
import { WorkspaceRepository } from '@database/types';
import sql from '@databases/resources/postgres/config';
import { WorkspacesRepository } from '@databases/types';
import { isEmpty } from 'lodash';

export class PostgresWorkspaceDatabase implements WorkspaceRepository {
export class PSQLWorkspacesDB implements WorkspacesRepository {
async createWorkspace(name: string): Promise<string> {
const results = await sql`
INSERT INTO workspace (name)
VALUES (${name})
RETURNING id
`;
if (results.length === 0) throw new Error('Workspace not created');
if (isEmpty(results)) throw new Error('Workspace not created');
return results[0].id;
}

Expand All @@ -21,7 +22,7 @@ export class PostgresWorkspaceDatabase implements WorkspaceRepository {

async getWorkspace(id: string): Promise<WorkspaceMetaData> {
const results: WorkspaceMetaData[] = await sql`SELECT * FROM workspace WHERE id = ${id}`;
if (results.length === 0) throw new NotFoundError(`Workspace with id ${id} not found`);
if (isEmpty(results)) throw new NotFoundError(`Workspace with id ${id} not found`);
return results[0];
}

Expand All @@ -31,12 +32,12 @@ export class PostgresWorkspaceDatabase implements WorkspaceRepository {
SET name = ${name}
WHERE id = ${id}
`;
if (results.length === 0) throw new NotFoundError(`Workspace with id ${id} not found`);
if (isEmpty(results)) throw new NotFoundError(`Workspace with id ${id} not found`);
}

async deleteWorkspace(id: string): Promise<void> {
const results = await sql`DELETE FROM workspace WHERE id = ${id}`;
if (results.length === 0) throw new NotFoundError(`Workspace with id ${id} not found`);
if (isEmpty(results)) throw new NotFoundError(`Workspace with id ${id} not found`);
}

async getWorkspaceResources(id: string): Promise<WorkspaceResource[]> {
Expand Down
Loading

0 comments on commit 88bbdc8

Please sign in to comment.