├── Insomnia.json
├── LICENSE
├── README.md
├── package.json
└── src
├── app.js
├── controllers
└── UserController.js
├── data
└── users.txt
├── middlewares
├── Exception.js
└── MiddlewareException.js
├── repositories
└── UserRepository.js
├── services
└── UserServices.js
└── utils
├── getParam.js
├── idGenerator.js
├── response.js
├── validateParam.js
└── validateType.js
/Insomnia.json:
--------------------------------------------------------------------------------
1 | {"_type":"export","__export_format":4,"__export_date":"2021-05-16T18:10:30.925Z","__export_source":"insomnia.desktop.app:v2021.3.0","resources":[{"_id":"req_7798205518334c288330749480bca1c1","parentId":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","modified":1621180586120,"created":1621119605343,"url":"{{ _.baseURL }}/users/","name":"List All","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621113316544.3125,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621119595972,"created":1621119595972,"name":"Users","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1621119595972,"_type":"request_group"},{"_id":"wrk_0e677ea7e62e47efb96e1979a517ebdc","parentId":null,"modified":1621019111231,"created":1621019111231,"name":"http_node_api","description":"","scope":"collection","_type":"workspace"},{"_id":"req_4cb5cde96ea54c2997f10d7972f62ed5","parentId":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","modified":1621188597556,"created":1621138162428,"url":"{{ _.baseURL }}/users/:uid","name":"List One","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621113316494.3125,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_06fab95e30ac4185bca6ff4e6822c184","parentId":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","modified":1621188592110,"created":1621133744517,"url":"{{ _.baseURL }}/users/data?","name":"Create","description":"","method":"POST","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621113316481.8125,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_d247d5f09ccf46068e55127cca4249bb","parentId":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","modified":1621188586832,"created":1621124040169,"url":"{{ _.baseURL }}/users/:uid/data?","name":"Update","description":"","method":"PUT","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621113316469.3125,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_9132519f760c471fa9dde512e29514c5","parentId":"fld_de0a0f81f7bb43b8ba86a8c86fc11422","modified":1621188576612,"created":1621129912035,"url":"{{ _.baseURL }}/users/:uid","name":"Delete","description":"","method":"DELETE","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621113316444.3125,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_811372df07854c0aa49175c00c285ed1","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621188567503,"created":1621124231602,"url":"{{ _.baseURL }}/abc","name":"404","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621069359350.5,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_1b1ca763243f4037a8d8081445101e6f","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621138148431,"created":1621019122728,"url":"{{ _.baseURL }}","name":"Welcome","description":"","method":"GET","body":{},"parameters":[],"headers":[],"authentication":{},"metaSortKey":-1621019122729,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_d235acc8c37e45c6f2d301b285ee21d7b77021cd","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621119776844,"created":1621019111319,"name":"Base Environment","data":{"baseURL":"localhost:3333"},"dataPropertyOrder":{"&":["baseURL"]},"color":null,"isPrivate":false,"metaSortKey":1621019111319,"_type":"environment"},{"_id":"jar_d235acc8c37e45c6f2d301b285ee21d7b77021cd","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621019111321,"created":1621019111321,"name":"Default Jar","cookies":[],"_type":"cookie_jar"},{"_id":"spc_330a2acce67345c9966d8346ae8c08f7","parentId":"wrk_0e677ea7e62e47efb96e1979a517ebdc","modified":1621019111238,"created":1621019111238,"fileName":"http_node_api","contents":"","contentType":"yaml","_type":"api_spec"}]}
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 João Victor Negreiros
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 | API 100% NodeJS
5 |
6 |
7 | Uma api sem dependências!
8 |
9 |

10 |

11 |
12 |
13 |
14 |
15 |
16 | ---
17 |
18 | Conteúdos
19 |
20 | [➜ Sobre o projeto](#mag_right-sobre-o-projeto)
21 | [➜ O que aprendi](#books-o-que-aprendi)
22 | [➜ Como usar](#information_source-como-usar)
23 | [➜ Rotas](#arrow_right_hook-rotas)
24 |
25 | ---
26 |
27 | ## :mag_right: Sobre o projeto
28 |
29 | [Voltar ao topo](#conteudos)
30 |
31 | O objetivo dessa aplicação era criar uma API sem nenhuma dependência externa, apenas utilizando as bibliotecas nativas do NodeJS. Tudo foi feito utilizando 100% Javascript.
32 |
33 | ---
34 |
35 | ### ➡ Front-end
36 | O front-end dessa API também foi feito utilizando 100% Javascript, sem arquivos HTML e CSS pré-criados.
37 |
38 | Para visualizar o resultado acesse o repositório: [joaovictornsv/http-node-api-web](https://github.com/joaovictornsv/http-node-api-web)
39 |
40 | ---
41 |
42 | ### ➡ Banco de Dados
43 | Não foi utilizado nenhum banco de dados, os registros são armazenados em um arquivo `users.txt`. Escolhi trabalhar com txt ao invés de JSON para ter o desafio de ler arquivos usando o Node.
44 |
45 | ---
46 |
47 | ### ➡ Arquitetura
48 | Tentei utilizar, na medida do possível, o conceito da Clean Architecture, separando os arquivos em Controllers, Services e Repository.
49 |
50 | ---
51 |
52 | ### ➡ Tratamento de erros
53 | Como o módulo `http` nativo do Node não nos permite usar o `request.body`, tive que adaptar minhas rotas e validar os dados passados por elas.
54 | Além disso, a estrutura da rota também foi validada, pois diferente de bibliotecas como o ExpressJS, onde passar a string `/users/:id` em uma função de request já nos permite acessar o parâmetro com facilidade, no Node esse acesso não é permitido. Para isso tive que criar modos de obtê-los.
55 |
56 | Para os tratamentos e validações utilizei as famosas RegEx's, as quais aprendi bastante sobre como atuam durante o desenvolvimento desse projeto.
57 |
58 | ---
59 |
60 | ### ➡ Funcionalidades ✔️
61 | A API possui um sistema de CRUD completo (Create, Read, Update and Delete) e possui as seguintes funcionalidades:
62 |
63 | #### Funções principais:
64 | - Listagem de usuários ou usuário único
65 | - Criação de novo usuário
66 | - Alteração de dados de um usuário
67 | - Remoção de um usuário
68 |
69 | #### Outras funcionalidades:
70 | - Validação de dados
71 | - Validação de rotas
72 | - Tratamento de erros usando Middlewares
73 | - Gerador de IDs únicos
74 | - Uso de Controller, Repository e Services
75 |
76 | ---
77 |
78 | ## :books: O que aprendi
79 |
80 | [Voltar ao topo](#conteudos)
81 |
82 | Ter que implementar cada etapa da api, desde o tratamento dos dados até o retorno da resposta para o cliente contribuiu bastante para treinar minha lógica de programação, a eficiência em resolver problemas pequenos e também a criar códigos mais legíveis e limpos.
83 | Além disso, aprendi a utilizar RegEx's para realizar várias validações no projeto. Por fim, acredito que criar essa API "pura" me fez evoluir mais um degrau nessa jornada de back-end.
84 |
85 | ---
86 |
87 | ## :information_source: Como usar
88 |
89 | [Voltar ao topo](#conteudos)
90 |
91 | ```bash
92 | # Clone this repository
93 | $ git clone https://github.com/joaovictornsv/http-node-api
94 |
95 | # Go into the repository
96 | $ cd http-node-api
97 |
98 | # Run the server
99 | $ yarn start
100 | ```
101 |
102 | ---
103 |
104 | ## :arrow_right_hook: Rotas
105 |
106 | [Voltar ao topo](#conteudos)
107 |
108 | [](https://insomnia.rest/run/?label=http-node-api&uri=https%3A%2F%2Fraw.githubusercontent.com%2Fjoaovictornsv%2Fhttp-node-api%2Fmaster%2FInsomnia.json)
109 |
110 |
111 |
112 | Ver rotas
113 |
114 |
115 |
116 |
117 | 
118 |
119 | - Home page
120 |
121 | ```
122 | /
123 | ```
124 |
125 | - Get all users
126 |
127 | ```
128 | /users
129 | ```
130 |
131 | - Get a specific user
132 | ```
133 | /users/:id
134 | ```
135 |
136 | ---
137 |
138 | 
139 | - Create a user
140 |
141 | ```
142 | users/data?...
143 |
144 | Search params:
145 | - name
146 | - email
147 | - age
148 | - city
149 | ```
150 |
151 | ---
152 |
153 | 
154 | - Update a user
155 |
156 | ```
157 | users/:id/data?...
158 |
159 | Search params:
160 | - name
161 | - email
162 | - age
163 | - city
164 | ```
165 |
166 | ---
167 |
168 | 
169 |
170 | - Delete a user
171 |
172 | ```
173 | /users/:id
174 | ```
175 |
176 |
177 | ---
178 |
179 |
183 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http-node-api",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "start": "node src/app.js"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | const http = require('http');
2 | const _ = require('url');
3 | const path = require('path');
4 |
5 | const UserController = require('./controllers/UserController');
6 | const MiddlewareException = require('./middlewares/MiddlewareException');
7 | const {
8 | getRE, postRE, putRE, getParam,
9 | } = require('./utils/getParam');
10 |
11 | const validateParam = require('./utils/validateParam');
12 |
13 | const filePath = path.resolve(__dirname, 'data', 'users.txt');
14 |
15 | const userController = new UserController(filePath);
16 | const middlewareException = new MiddlewareException();
17 |
18 | const app = http.createServer(async (req, res) => {
19 | const url = new _.URL(`http://localhost:3333${req.url}`);
20 | const { method } = req;
21 |
22 | const route = url.pathname;
23 |
24 | try {
25 | if (route === '/') {
26 | res.writeHead(200, { 'content-type': 'application/json' });
27 | res.write(JSON.stringify({ welcome: 'http node api' }));
28 |
29 | return res.end();
30 | }
31 |
32 | if (method === 'GET' && route.match(getRE)) {
33 | const id = getParam(route);
34 |
35 | if (id) {
36 | return await userController.indexUser(res, id);
37 | }
38 |
39 | return await userController.index(res);
40 | }
41 |
42 | if (method === 'POST' && route.match(postRE)) {
43 | const name = validateParam(url.searchParams.get('name'), 'string', 'name');
44 | const email = validateParam(url.searchParams.get('email'), 'email', 'email');
45 | const age = validateParam(url.searchParams.get('age'), 'number', 'age');
46 | const city = validateParam(url.searchParams.get('city'), 'string', 'city');
47 |
48 | const user = {
49 | name, age, city, email,
50 | };
51 |
52 | return await userController.addUser(res, user);
53 | }
54 |
55 | if (method === 'PUT' && route.match(putRE)) {
56 | const id = getParam(route);
57 | const name = validateParam(url.searchParams.get('name'), 'string', 'name');
58 | const email = validateParam(url.searchParams.get('email'), 'email', 'email');
59 | const age = validateParam(url.searchParams.get('age'), 'number', 'age');
60 | const city = validateParam(url.searchParams.get('city'), 'string', 'city');
61 |
62 | const user = {
63 | id, name, age, city, email,
64 | };
65 |
66 | return await userController.updateUser(res, user);
67 | }
68 |
69 | if (method === 'DELETE' && route.match(getRE)) {
70 | const id = getParam(route);
71 |
72 | return await userController.deleteUser(res, id);
73 | }
74 | // 404
75 |
76 | res.setHeader('Access-Control-Allow-Origin', "*");
77 | res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
78 |
79 | res.writeHead(200, { 'content-type': 'application/json' });
80 | res.write(JSON.stringify({erro:`Cannot ${method} ${route}`}));
81 | return res.end();
82 | } catch (err) {
83 | middlewareException.handle(res, err);
84 | return res.end();
85 | }
86 | });
87 |
88 | app.listen(3333, () => console.log('Server is listening on port 3333.'));
89 |
--------------------------------------------------------------------------------
/src/controllers/UserController.js:
--------------------------------------------------------------------------------
1 | const UserServices = require('../services/UserServices');
2 | const response = require('../utils/response');
3 |
4 | class UserController {
5 | constructor(path) {
6 | this.path = path;
7 | }
8 |
9 | async index(res) {
10 | const userServices = new UserServices(this.path);
11 |
12 | const users = await userServices.getAllUsers();
13 |
14 | return response(res, users);
15 | }
16 |
17 | async indexUser(res, id = '') {
18 | const userServices = new UserServices(this.path);
19 |
20 | const user = await userServices.getUser(id);
21 |
22 | return response(res, user);
23 | }
24 |
25 | async addUser(res, user) {
26 | const userServices = new UserServices(this.path);
27 |
28 | const newUser = await userServices.createUser(user);
29 |
30 | return response(res, newUser, 201);
31 | }
32 |
33 | async updateUser(res, user) {
34 | const userServices = new UserServices(this.path);
35 |
36 | const newUser = await userServices.modifyUser(user);
37 |
38 | return response(res, newUser);
39 | }
40 |
41 | async deleteUser(res, id) {
42 | const userServices = new UserServices(this.path);
43 |
44 | await userServices.removeUser(id);
45 |
46 | return response(res, { message: `User with id '${id}' deleted!` });
47 | }
48 | }
49 | module.exports = UserController;
50 |
--------------------------------------------------------------------------------
/src/data/users.txt:
--------------------------------------------------------------------------------
1 | uid;name;email;age;city
--------------------------------------------------------------------------------
/src/middlewares/Exception.js:
--------------------------------------------------------------------------------
1 | class Exception {
2 | constructor(message, statusCode = 400, contentType = 'application/json') {
3 | this.statusCode = statusCode;
4 | this.contentType = { 'content-type': contentType };
5 | this.message = JSON.stringify({ error: message });
6 | }
7 | }
8 |
9 | module.exports = Exception;
10 |
--------------------------------------------------------------------------------
/src/middlewares/MiddlewareException.js:
--------------------------------------------------------------------------------
1 | const Exception = require('./Exception');
2 |
3 | class MiddlewareException {
4 | handle(res, error) {
5 | res.setHeader('Access-Control-Allow-Origin', "*");
6 | res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
7 | if (error instanceof Exception) {
8 | res.writeHead(error.statusCode, error.contentType);
9 | res.write(error.message);
10 | } else {
11 | console.log(error);
12 | res.write(error);
13 | }
14 | }
15 | }
16 |
17 | module.exports = MiddlewareException;
18 |
--------------------------------------------------------------------------------
/src/repositories/UserRepository.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs').promises;
2 |
3 | class UserRepository {
4 | constructor(path) {
5 | this.file = path;
6 | }
7 |
8 | async find() {
9 | const file = await fs.readFile(this.file, 'utf8');
10 | const lines = file.split('\n').splice(1);
11 | if (!lines) {
12 | return [];
13 | }
14 | const data = lines.map((line) => {
15 | let [id, name, email, age, city] = line.split(';');
16 |
17 | age = parseInt(age);
18 |
19 | return {
20 | id, name, email, age, city,
21 | };
22 | });
23 |
24 | return data;
25 | }
26 |
27 | async append(user) {
28 | const {
29 | id, name, email, age, city,
30 | } = user;
31 |
32 | await fs.writeFile(this.file, `\n${id};${name};${email};${age};${city}`, { flag: 'a' });
33 | }
34 |
35 | async write(user) {
36 | const {
37 | id, name, age, email, city,
38 | } = user;
39 |
40 | await fs.writeFile(this.file, `${id};${name};${email};${age};${city}`);
41 | }
42 |
43 | async findByID(id) {
44 | const users = await this.find();
45 | const user = users.find((u) => {
46 | if (u.id === id) {
47 | return u;
48 | }
49 | });
50 |
51 | return user;
52 | }
53 |
54 | async findByEmail(email) {
55 | const users = await this.find();
56 | const user = users.find((u) => {
57 | if (u.email === email) {
58 | return u;
59 | }
60 | });
61 |
62 | return user;
63 | }
64 |
65 | async updateData(data) {
66 | const overwrite = async () => {
67 | if (data.length === 0) {
68 | await fs.writeFile(this.file, 'uid;name;email;age;city');
69 | } else {
70 | for (let i = 0; i < data.length; i++) {
71 | if (i === 0) {
72 | await fs.writeFile(this.file, 'uid;name;email;age;city');
73 | await this.append(data[i]);
74 | } else {
75 | await this.append(data[i]);
76 | }
77 | }
78 | }
79 | };
80 |
81 | await overwrite();
82 | }
83 | }
84 |
85 | module.exports = UserRepository;
86 |
--------------------------------------------------------------------------------
/src/services/UserServices.js:
--------------------------------------------------------------------------------
1 | const UserRepository = require('../repositories/UserRepository');
2 | const Exception = require('../middlewares/Exception');
3 | const { uid, authID } = require('../utils/idGenerator');
4 |
5 | class UserServices {
6 | constructor(path) {
7 | this.userRepository = new UserRepository(path);
8 | }
9 |
10 | async getAllUsers() {
11 | let users;
12 | await this.userRepository.find()
13 | .then((result) => {
14 | users = result;
15 | })
16 | .catch((err) => {
17 | console.error(err);
18 | throw new Exception('Error reading database');
19 | })
20 |
21 | return users;
22 | }
23 |
24 | async getUser(id) {
25 | const userExists = await this.userRepository.findByID(id);
26 |
27 | if (!authID(id)) {
28 | throw new Exception("The 'id must be of type 'uid'");
29 | }
30 |
31 | if (!userExists) {
32 | throw new Exception('User with this id does not exists');
33 | }
34 |
35 | return userExists;
36 | }
37 |
38 | async createUser(user) {
39 | const {
40 | name, age, city, email,
41 | } = user;
42 |
43 | if (!name || !age || !city || !email) {
44 | throw new Exception('This params are incorret!');
45 | }
46 |
47 | const userAlreadyExists = await this.userRepository.findByEmail(email);
48 |
49 | if (userAlreadyExists) {
50 | throw new Exception('An user with this email already exists');
51 | }
52 |
53 | user.id = uid();
54 |
55 | await this.userRepository.append(user);
56 |
57 | return user;
58 | }
59 |
60 | async modifyUser(user) {
61 | if (!user.id) {
62 | throw new Exception('Id not provided!');
63 | }
64 |
65 | if (!authID(user.id)) {
66 | throw new Exception("The 'id must be of type 'uid'");
67 | }
68 |
69 | if (!user.name && !user.age && !user.city && !user.email) {
70 | throw new Exception('No fields to edit provided!');
71 | }
72 |
73 | const userExists = await this.userRepository.findByID(user.id);
74 |
75 | if (!userExists) {
76 | throw new Exception('User with this id does not exist');
77 | }
78 |
79 | const changes = [];
80 |
81 | user.name && changes.push(['name', user.name]);
82 | user.email && changes.push(['email', user.email]);
83 | user.age && changes.push(['age', user.age]);
84 | user.city && changes.push(['city', user.city]);
85 |
86 | const users = await this.userRepository.find();
87 |
88 | const usersUpdated = users.map((u) => {
89 | if (u.id === user.id) {
90 | changes.forEach((change) => {
91 | const [key, value] = change;
92 | u[key] = value;
93 | });
94 | }
95 |
96 | return u;
97 | });
98 |
99 | await this.userRepository.updateData(usersUpdated);
100 |
101 | return this.userRepository.findByID(user.id);
102 | }
103 |
104 | async removeUser(id) {
105 | if (!id) {
106 | throw new Exception('Id not provided!');
107 | }
108 |
109 | if (!authID(id)) {
110 | throw new Exception("The 'id must be of type 'uid'");
111 | }
112 |
113 | const userExists = await this.userRepository.findByID(id);
114 |
115 | if (!userExists) {
116 | throw new Exception('User does not exist');
117 | }
118 |
119 | const users = await this.userRepository.find();
120 |
121 | const usersUpdated = users.filter((user) => {
122 | if (user.id !== id) {
123 | return user;
124 | }
125 | });
126 |
127 | await this.userRepository.updateData(usersUpdated);
128 | }
129 | }
130 |
131 | module.exports = UserServices;
132 |
--------------------------------------------------------------------------------
/src/utils/getParam.js:
--------------------------------------------------------------------------------
1 | const getRE = /\/(users)\/?([0-9a-z]|(\-))*?\/?$/g;
2 | const putRE = /^\/(users)\/([0-9a-z]|(\-))*\/(data((?!((\/)|(\?\/)))))/g;
3 | const postRE = /^\/(users)\/(data((?!((\/)|(\?\/)))))/g;
4 |
5 | function getParam(route) {
6 | const allParams = route.split('/');
7 | let param = null;
8 | if (allParams.length >= 3) {
9 | param = allParams[2];
10 |
11 | if (param === '') {
12 | param = null;
13 | }
14 | }
15 |
16 | return param;
17 | }
18 |
19 | module.exports = {
20 | getRE, postRE, putRE, getParam,
21 | };
22 |
--------------------------------------------------------------------------------
/src/utils/idGenerator.js:
--------------------------------------------------------------------------------
1 | function encrypt(number) {
2 | let numberEncrypt = number.toString().replace('0', 'o');
3 | numberEncrypt = numberEncrypt.replace('1', 'i');
4 | numberEncrypt = numberEncrypt.replace('3', 'e');
5 | numberEncrypt = numberEncrypt.replace('4', 'a');
6 | numberEncrypt = numberEncrypt.replace('5', 's');
7 |
8 | return numberEncrypt;
9 | }
10 |
11 | function authID(id) {
12 | const uidRE = /^(uid-j[0-9a-z*]*-v[0-9a-z*]*-j[0-9a-z*]*-v[0-9a-z*]*)$/g;
13 |
14 | if (id.toString().match(uidRE)) {
15 | return true;
16 | }
17 | return false;
18 | }
19 |
20 | function uid() {
21 | const date = new Date();
22 |
23 | const increment = date.getDay() + date.getMonth() + date.getFullYear();
24 |
25 | const UTCMilli = date.getUTCMilliseconds();
26 |
27 | const first =
28 | date.getMilliseconds() * (UTCMilli + 10) * (UTCMilli + 20)
29 | * (parseInt(Math.random() * 10) + parseInt(Math.random() * 10) + 1)
30 | + increment;
31 |
32 | const second =
33 | (date.getSeconds()+1) * (date.getUTCSeconds()+1) * (UTCMilli + 30)
34 | * (parseInt(Math.random() * 10) + parseInt(Math.random() * 10) + 2)
35 | + increment;
36 |
37 | const third =
38 | (date.getMinutes()+1) * (date.getUTCMinutes()+1) * (UTCMilli + 40)
39 | * (parseInt(Math.random() * 10) + parseInt(Math.random() * 10) + 3)
40 | + increment;
41 |
42 | const fourth =
43 | (date.getHours()+1) * (date.getUTCHours()+1) * (UTCMilli + 50)
44 | * (parseInt(Math.random() * 10) + parseInt(Math.random() * 10) + 4)
45 | + increment;
46 |
47 | const id = `uid-j${encrypt(first)}-v${encrypt(second)}-j${encrypt(third)}-v${encrypt(fourth)}`;
48 |
49 | return id;
50 | }
51 |
52 | module.exports = { uid, authID };
53 |
--------------------------------------------------------------------------------
/src/utils/response.js:
--------------------------------------------------------------------------------
1 | function response(res, data = {}, statusCode = 200, contentType = 'application/json') {
2 | res.setHeader('Access-Control-Allow-Origin', "*");
3 | res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,PUT,DELETE');
4 | res.writeHead(statusCode, { 'content-type': contentType});
5 | res.write(JSON.stringify(data));
6 |
7 | return res.end();
8 | }
9 |
10 | module.exports = response;
11 |
--------------------------------------------------------------------------------
/src/utils/validateParam.js:
--------------------------------------------------------------------------------
1 | const validateType = require('./validateType');
2 | const Exception = require('../middlewares/Exception')
3 |
4 | function validateParam(param, type, field) {
5 | if (!param) {
6 | return null;
7 | }
8 |
9 | const searchParamRE = /^((?!((\/)|(\;))).)*$/g;
10 |
11 | if (param.match(searchParamRE)) {
12 | return validateType(param, type, field);
13 | } else {
14 | throw new Exception('Invalid params');
15 | }
16 | }
17 |
18 | module.exports = validateParam;
19 |
--------------------------------------------------------------------------------
/src/utils/validateType.js:
--------------------------------------------------------------------------------
1 | const Exception = require('../middlewares/Exception');
2 |
3 | function validateType(param, type, field) {
4 | let Vparam = param;
5 | const Vtype = type;
6 |
7 | if (Vtype === 'number') {
8 | Vparam = parseInt(Vparam, 10);
9 |
10 | if (typeof Vparam === Vtype && !isNaN(Vparam)) {
11 | return Vparam;
12 | }
13 | }
14 |
15 | if (Vtype === 'email') {
16 | const emailRE = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/g;
17 |
18 | if (Vparam.match(emailRE)) {
19 | return Vparam;
20 | }
21 | }
22 |
23 | if (Vtype === 'string') {
24 | return Vparam;
25 | }
26 |
27 | throw new Exception(`The field '${field}' must be of type '${Vtype}'`);
28 | }
29 |
30 | module.exports = validateType;
31 |
--------------------------------------------------------------------------------