Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ It must work perfectly together with the backend.
Include UI libraries to improve the app’s appearance. (Choose the one you prefer).
Implement a method to delete any item in the TODO List.
Implement a method to update any item in the TODO List.


In a real environment the env files would not be in the repository, I left them in the repository to make review easier
1. Start the application

- Using: `./start.sh --install` you will initialize the application and install the dependencies(It is mandatory to use this command the first time you run it.)
- Using: `./start.sh` You will start the application without the need to install dependencies.

6. Using the app

- After that, just log in to localhost:3000.
4 changes: 4 additions & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.git
.gitignore
/node_modules
/build
6 changes: 6 additions & 0 deletions backend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SERVER_PORT=3001
SERVER_HOST=172.16.238.3
MONGO_HOST_SERVER=172.16.238.2
MONGO_INITDB_ROOT_USERNAME=mongo
MONGO_INITDB_ROOT_PASSWORD=mongo
MONGO_INITDB_DATABASE=mongo
8 changes: 8 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
SERVER_PORT=
CRYPTO_SECRET_KEY=
SERVER_HOST=
POSTGRES_HOST_SERVER=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
POSTGRES_PORT=
2 changes: 2 additions & 0 deletions backend/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/*.js
node_modules
47 changes: 47 additions & 0 deletions backend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"env": {
"node": true,
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint", "prettier"],
"rules": {
"prettier/prettier": "error",
"no-console": "warn",
"no-debugger": "warn",
"curly": ["error", "all"],
"prefer-const": "error",
"no-var": "error",
"consistent-return": "warn",
"default-case": "warn",
"no-duplicate-imports": "error",
"no-unreachable": "warn",
"no-unused-vars": "warn",
"no-undef": "error",
"semi": ["error", "always"],
"quotes": ["error", "single"],
"indent": ["error", 2],
"max-len": ["error", { "code": 100, "ignoreUrls": true }],
"arrow-body-style": ["error", "as-needed"],
"no-implicit-coercion": "error",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/explicit-module-boundary-types": "warn",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/explicit-function-return-type": [
"warn",
{
"allowExpressions": true
}
],
"@typescript-eslint/no-inferrable-types": "off"
}
}
3 changes: 3 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
/coverage
/build
9 changes: 9 additions & 0 deletions backend/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"singleQuote": true,
"trailingComma": "all",
"semi": true,
"tabWidth": 2,
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always"
}
14 changes: 14 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM node:20.6.0-alpine

WORKDIR /usr/

COPY package*.json ./

RUN npm install

COPY . .


EXPOSE 3001

CMD ["sh", "-c", "npm run build && npm run pm2:start"]
45 changes: 0 additions & 45 deletions backend/dist/index.js

This file was deleted.

43 changes: 43 additions & 0 deletions backend/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
version: '3.9'
networks:
internal_UJJigBWx:
driver: bridge
ipam:
config:
- subnet: 172.16.238.0/24
driver: default

services:
mongo:
image: mongo:6
container_name: mongo
environment:
MONGO_INITDB_ROOT_USERNAME: mongo
MONGO_INITDB_ROOT_PASSWORD: mongo
MONGO_INITDB_DATABASE: mongo
ports:
- '27017:27017'
volumes:
- mongo-data:/data/db
networks:
internal_UJJigBWx:
ipv4_address: ${MONGO_HOST_SERVER}

backend:
build: .
container_name: backend
volumes:
- ./:/usr/src/app
- /usr/src/app/node_modules
working_dir: '/usr/src/app'
env_file: [./.env]
ports: ['3001:3001']
depends_on:
- mongo
networks:
internal_UJJigBWx:
ipv4_address: ${SERVER_HOST}

volumes:
mongo-data:
driver: local
14 changes: 14 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 17 additions & 4 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,32 @@
"version": "1.0.0",
"main": "dist/index.js",
"scripts": {
"start": "node dist/index.js",
"dev": "ts-node-dev --respawn src/index.ts",
"build": "tsc"
"pm2:start": "pm2-runtime build/server.js -i max",
"pm2:stop": "pm2 stop build/server.js",
"build": "tsc",
"start:build": "node build/server.js",
"start:dev": "nodemon -L --exec 'ts-node server.ts' -e ts",
"climem": "npx climem 8999",
"loadtest": "npx autocannon -c 100 -p 10 -d 10 -m 'POST' http://localhost:3001/api/health --renderStatusCodes"
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"body-parser": "^1.20.2",
"dotenv": "^16.3.1",
"joi": "^17.13.3",
"node-cache": "^5.1.2",
"pm2": "^5.3.0",
"mongoose": "^7.0.0"
},
"devDependencies": {
"@types/cors": "^2.8.14",
"@types/express": "^4.17.15",
"@types/mongoose": "^5.11.97",
"@types/node": "^20.5.9",
"nodemon": "^3.0.1",
"prettier": "^3.4.2",
"ts-node": "^10.9.1",
"typescript": "^5.0.0"
"typescript": "^5.8.2"
}
}
47 changes: 47 additions & 0 deletions backend/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as dotenv from 'dotenv';
import cors from 'cors';
import { Request, Response, NextFunction } from 'express';
import express from 'express';
import bodyParser from 'body-parser';

import router from './src/routes';
import { Exception } from './src/typings/interfaces';
import protect from './src/middlewares/auth.middleware';
import { connectDB } from './src/infra/database/dbConfig';
dotenv.config();
const { SERVER_PORT } = process.env;

const processId = process.pid;
const app = express();

app.use(cors());
app.use(express.json());
app.use(
bodyParser.json({
limit: '50mb',
}),
);
app.use(
bodyParser.urlencoded({
limit: '50mb',
extended: true,
parameterLimit: 50000,
}),
);

app.use((req: any, res: Response, next: NextFunction) => protect(req, res, next));

app.use('/', router);

app.use((error: Exception, _req: Request, res: Response, next: NextFunction) => {
const { message, status } = error;
if (status && status < 500) {
return res.status(status).json({ message });
}
return res.status(500).json({ message: 'Something broke!' });
});

app.listen(SERVER_PORT, async () => {
await connectDB();
console.log(`Running on http://localhost:${SERVER_PORT} with pid: ${processId}`);
});
8 changes: 8 additions & 0 deletions backend/src/domain/entities/base.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Types } from 'mongoose';

export abstract class BaseEntity {
_id!: Types.ObjectId;
createdAt?: Date;
updatedAt?: Date;
deletedAt?: Date;
}
2 changes: 2 additions & 0 deletions backend/src/domain/entities/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './base.entity';
export * from './task.entity';
15 changes: 15 additions & 0 deletions backend/src/domain/entities/task.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { BaseEntity } from './base.entity';

export interface TaskAttributes {
id: string;
title: string;
completed: boolean;
completedAt: Date | null;
}

export class Task extends BaseEntity implements TaskAttributes {
public id!: string;
public title!: string;
public completed!: boolean;
public completedAt!: Date | null;
}
12 changes: 12 additions & 0 deletions backend/src/domain/repositories/base.repository.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface IBaseRepository<T> {
create: (entity: T) => Promise<T>;
findOne: (filter: Partial<T>) => Promise<T | null>;
findMany: (filter: any) => Promise<{
data: T[] | [];
page: number;
totalPages: number;
totalItems: number;
}>;
updateOne: (filter: Partial<T>, entity: Partial<T>) => Promise<T | boolean>;
delete: (entity: T) => Promise<T | boolean>;
}
2 changes: 2 additions & 0 deletions backend/src/domain/repositories/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './base.repository.interface';
export * from './task.repository.interface';
5 changes: 5 additions & 0 deletions backend/src/domain/repositories/task.repository.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Task } from '../entities';
import { IBaseRepository } from './base.repository.interface';

export interface ITaskRepository extends IBaseRepository<Task> {
}
7 changes: 7 additions & 0 deletions backend/src/exceptions/bad-request.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { BaseException } from './base.exception';

export class BadRequestException extends BaseException {
constructor(message: string) {
super(message, 400);
}
}
9 changes: 9 additions & 0 deletions backend/src/exceptions/base.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export class BaseException extends Error {
message: string;
status: number;
constructor(message: string, status: number) {
super();
this.message = message;
this.status = status;
}
}
7 changes: 7 additions & 0 deletions backend/src/exceptions/conflict.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { BaseException } from './base.exception';

export class ConflictException extends BaseException {
constructor(message: string) {
super(message, 409);
}
}
5 changes: 5 additions & 0 deletions backend/src/exceptions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './base.exception';
export * from './conflict.exception';
export * from './unprocessable-content.exception';
export * from './not-found.exception';
export * from './bad-request.exception';
Loading