Skip to content

Commit

Permalink
REST components update
Browse files Browse the repository at this point in the history
* Added Services
* Added Database
* Added Handlers
  • Loading branch information
GuilhermeF03 committed May 9, 2024
1 parent 78c91c5 commit 7d73b22
Show file tree
Hide file tree
Showing 25 changed files with 356 additions and 178 deletions.
2 changes: 1 addition & 1 deletion code/client/src/services/documentServices.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { HttpCommunication } from '@/services/communication/http/httpCommunication';
import { Document } from '@notespace/shared/workspace/types/document.ts';
import { Document } from '@notespace/shared/workspace/types/document.d.ts';

async function getDocument(http: HttpCommunication, id: string): Promise<Document> {
const { operations, title } = await http.get(`/documents/${id}`);
Expand Down
2 changes: 1 addition & 1 deletion code/client/src/ui/pages/workspace/Workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { useCommunication } from '@/services/communication/context/useCommunication';
import { DocumentData } from '@notespace/shared/workspace/types/document.ts';
import { DocumentData } from '@notespace/shared/workspace/types/document.d.ts';
import WorkspaceHeader from '@ui/pages/workspace/components/WorkspaceHeader';
import DocumentPreview from '@ui/pages/workspace/components/DocumentPreview';
import useError from '@domain/error/useError';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IoDocumentText } from 'react-icons/io5';
import { Link } from 'react-router-dom';
import { DocumentData } from '../../../../../../shared/workspace/types/document.ts';
import { DocumentData } from '@notespace/shared/workspace/types/document.d.ts';
import DocumentContextMenu from '@ui/pages/workspace/components/DocumentContextMenu';
import { useEffect, useRef, useState } from 'react';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@notespace/shared/crdt/types/operations';
import getFugueOperations from '@domain/editor/operations/fugue/operations';
import { FugueDomainOperations } from '@domain/editor/operations/fugue/types';
import { Document } from '@notespace/shared/workspace/types/document.ts';
import { Document } from '@notespace/shared/workspace/types/document.d.ts';
import { Node, RootNode } from '@notespace/shared/crdt/types/nodes';
import { rootNode, treeNode } from '@notespace/shared/crdt/utils';

Expand Down
43 changes: 0 additions & 43 deletions code/server/src/ts/controllers/http/documentHandlers.ts

This file was deleted.

20 changes: 6 additions & 14 deletions code/server/src/ts/controllers/http/router.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
import express from 'express';
import PromiseRouter from 'express-promise-router';
import { DocumentService } from '@services/types';
import documentHandlers from '@controllers/http/documentHandlers';
import { DocumentService, NoteSpaceServices } from '@services/types';
import documentHandlers from '@controllers/http/workspace/documentHandlers';
import errorHandler from '@controllers/http/errorHandler';
import resourcesHandlers from '@controllers/http/workspace/resourcesHandlers';
import workspaceHandlers from '@controllers/http/workspace/workspaceHandlers';

export default function (service: DocumentService) {
export default function (service: NoteSpaceServices) {
if (!service) throw new Error('Service parameter is required');

const { getDocuments, createDocument, getDocument, deleteDocument, updateDocument } = documentHandlers(service);

const router = PromiseRouter(); // automatically routes unhandled errors to error handling middleware
router.use(express.urlencoded({ extended: true }));

router.get('/', (req, res) => {
res.send('Welcome to NoteSpace API');
});
router.get('/documents', getDocuments);
router.post('/documents', createDocument);
router.get('/documents/:id', getDocument);
router.delete('/documents/:id', deleteDocument);
router.put('/documents/:id', updateDocument);

router.use('/workspaces', workspaceHandlers(service));
router.use(errorHandler);
return router;
}
13 changes: 11 additions & 2 deletions code/server/src/ts/controllers/http/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { Response } from 'express';

export const httpResponse = {
ok: <T>(res: Response, data: T) => res.status(200).send(data),
created: <T>(res: Response, data: T) => res.status(201).send(data),
ok: (res: Response) => res.status(200),
created: (res: Response) => res.status(201),
noContent: (res: Response) => res.status(204).send(),

// Error responses
badRequest: (res: Response) => res.status(400),
unauthorized: (res: Response) => res.status(401),
forbidden: (res: Response) => res.status(403),
notFound: (res: Response) => res.status(404),
conflict: (res: Response) => res.status(409),
internalServerError: (res: Response) => res.status(500),
};

38 changes: 38 additions & 0 deletions code/server/src/ts/controllers/http/workspace/documentHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Request, Response } from 'express';
import { httpResponse } from '@controllers/http/utils';
import PromiseRouter from 'express-promise-router';
import { DocumentService } from '@services/documentService';

function documentHandlers(service: DocumentService) {

const router = PromiseRouter();

/**
* Open document - get document content saved in firestore
* @param req
* @param res
*/
const getDocument = async (req: Request, res: Response) => {
const { id: workspaceId, docId } = req.params;
const document = await service.getDocument(workspaceId, docId);
httpResponse.ok(res).json(document);
}

/**
* Update document - update document content in firestore - used for real-time operations that don't require postgres updates
* @param req
* @param res
*/
const updateDocument = async (req: Request, res: Response) => {
const {id, workspace, operations} = req.body // TODO: convert into InputModel
await service.updateDocument(workspace, id, operations);
httpResponse.noContent(res);
}

router.put('/', updateDocument);
router.get('/:docId', getDocument);

return router;
}

export default documentHandlers;
50 changes: 50 additions & 0 deletions code/server/src/ts/controllers/http/workspace/resourcesHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import PromiseRouter from 'express-promise-router';
import { NoteSpaceServices, ResourcesService } from '@services/types';
import { ResourceInputModel, WorkspaceResource } from '@notespace/shared/workspace/types/resource';
import { httpResponse } from '@controllers/http/utils';
import { Request, Response } from 'express';

function resourcesHandlers(services : ResourcesService) {
const router = PromiseRouter();

const createResource = async (req : Request, res : Response) => {
const resource = req.body as ResourceInputModel;
const id = await services.createResource(resource);
return httpResponse.created(res).json({ id });
}

const getResource = async (req : Request, res: Response) => {
const id = req.params.resId;
const resource = await services.getResource(id);

if (!resource) {
return httpResponse.notFound(res).send();
}

return httpResponse.ok(res).json(resource);
}

const updateResource = async (req : Request, res : Response) => {
const resource = req.body as Partial<WorkspaceResource>
if (!resource.id) {
return httpResponse.badRequest(res).send('Resource id is required');
}
await services.updateResource(resource);
return httpResponse.noContent(res).send();
}

const deleteResource = async (req : Request, res : Response) => {
const id = req.params.resId;
await services.deleteResource(id);
return httpResponse.noContent(res).send();
}

router.post('/', createResource);
router.get('/:resId', getResource);
router.put('/:resId', updateResource);
router.delete('/:resId', deleteResource);

return router;
}

export default resourcesHandlers;
45 changes: 45 additions & 0 deletions code/server/src/ts/controllers/http/workspace/workspaceHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import PromiseRouter from 'express-promise-router';
import { NoteSpaceServices } from '@services/types';
import { httpResponse } from '@controllers/http/utils';
import { Request, Response } from 'express';
import resourcesHandlers from '@controllers/http/workspace/resourcesHandlers';
import documentHandlers from '@controllers/http/workspace/documentHandlers';
import { WorkspaceInfo } from '@notespace/shared/workspace/types/workspace';

function workspaceHandlers(service : NoteSpaceServices){
const router = PromiseRouter();

const createWorkspace = async (req : Request, res : Response) => {
const { name } = req.body as WorkspaceInfo;
const id = await service.workspace.createWorkspace(name);
httpResponse.created(res).json({ id });
}

const getWorkspaceInfo = async (req : Request, res : Response) => {
const workspace = await service.workspace.getWorkspace(req.params.id);
httpResponse.ok(res).json(workspace);
}

const updateWorkspace = async (req : Request, res : Response) => {
const { id, name } = req.body as WorkspaceInfo;
await service.workspace.updateWorkspace(id, name);
httpResponse.noContent(res);
}

const deleteWorkspace = async (req : Request, res : Response) => {
await service.workspace.deleteWorkspace(req.params.id);
httpResponse.noContent(res);
}

router.post('/', createWorkspace);
router.put('/', updateWorkspace);
router.get('/:id', getWorkspaceInfo);
router.delete('/:id', deleteWorkspace);

router.use('/:id/resources', resourcesHandlers(service.resources));
router.use('/:id/documents', documentHandlers(service.document));

return router;
}

export default workspaceHandlers;
1 change: 1 addition & 0 deletions code/server/src/ts/database/pg/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ const credentials = {
const sql = postgres(credentials);

export default sql;

Empty file.
34 changes: 0 additions & 34 deletions code/server/src/ts/database/pg/postgresDB.ts

This file was deleted.

15 changes: 15 additions & 0 deletions code/server/src/ts/database/pg/resourcesDB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export class ResourcesDB {

async createResource(resource) {
return await this.database.createResource(resource);
}
async getResource(id) {
return await this.database.getResource(id);
}
async updateResource(resource) {
await this.database.updateResource(resource);
}
async deleteResource(id) {
await this.database.deleteResource(id);
}
}
37 changes: 37 additions & 0 deletions code/server/src/ts/database/pg/workspaceDB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { WorkspaceResource } from '@notespace/shared/workspace/types/resource';
import { WorkspaceInfo } from '@notespace/shared/workspace/types/workspace';
import sql from './database';
import { NotFoundError } from '@domain/errors/errors';


export class WorkspaceDB {

async createWorkspace(title: string) : Promise<string> {
const results = await sql`INSERT INTO workspace (title) VALUES (${title}) RETURNING id`;
return results[0].id;
}

async getWorkspace(workspace: string) : Promise<WorkspaceInfo> {
const results : WorkspaceInfo[] = await sql`SELECT * FROM workspace WHERE id = ${workspace}`;

if (results.length === 0) {
throw new NotFoundError(`Workspace with id ${workspace} not found`);
}
if (results.length > 1) {
throw new Error(`Multiple workspaces with id ${workspace} found`);
}
return results[0];
}

async updateWorkspace(id: string, name: string) : Promise<void> {

}

async deleteWorkspace(id: string) : Promise<void> {

}

async getWorkspaceResources(workspace: string) : Promise<WorkspaceResource[]> {
return sql`SELECT * FROM resource WHERE workspace = ${workspace}`;
}
}
Loading

0 comments on commit 7d73b22

Please sign in to comment.