Estruturação do Projeto
Arquivos
invest-app-mvc
├── package-lock.json
├── package.json
├── public
│ ├── css
│ │ └── style.css
│ ├── index.html
│ └── js
│ ├── index.js
│ ├── lib
│ │ └── format.js
│ └── services
│ └── api.js
├── requests.http
└── src
├── database
│ ├── data.js
│ ├── seeders.js
│ └── seeders.json
├── index.js
├── models
│ └── Investment.js
└── routes.js
Arquivos
invest-app-mvc
├── package-lock.json
├── package.json
├── public
│ ├── css
│ │ └── style.css
│ ├── index.html
│ └── js
│ ├── index.js
│ ├── lib
│ │ └── format.js
│ └── services
│ └── api.js
├── requests.http
└── src
├── database
│ ├── data.js
│ ├── seeders.js
│ └── seeders.json
├── index.js
├── models
│ └── Investment.js
└── routes.js
Database
/codes/expressjs/invest-app-mvc/src/database/data.js
export const investments = [];
/codes/expressjs/invest-app-mvc/src/database/data.js
export const investments = [];
Model
/codes/expressjs/invest-app-mvc/src/models/Investment.js
import { v4 as uuidv4 } from 'uuid';
import { investments } from '../database/data.js';
function create({ name, value }) {
const id = uuidv4();
const investment = { name, value, id };
if (name && value) {
investments.push(investment);
return investment;
} else {
throw new Error('Unable to create investment');
}
}
function read(field, value) {
if (field && value) {
const filteredInvestments = investments.filter((investment) =>
investment[field].includes(value)
);
return filteredInvestments;
}
return investments;
}
function readById(id) {
if (id) {
const index = investments.findIndex((investment) => investment.id === id);
if (!investments[index]) {
throw new Error('Investment not found');
}
return investments[index];
} else {
throw new Error('Unable to find investment');
}
}
function update({ id, name, value }) {
if (name && value && id) {
const newInvestment = { name, value, id };
const index = investments.findIndex((investment) => investment.id === id);
if (!investments[index]) {
throw new Error('Investment not found');
}
investments[index] = newInvestment;
return newInvestment;
} else {
throw new Error('Unable to update investment');
}
}
function remove(id) {
if (id) {
const index = investments.findIndex((investment) => investment.id === id);
investments.splice(index, 1);
return true;
} else {
throw new Error('Investment not found');
}
}
export default { create, read, readById, update, remove };
/codes/expressjs/invest-app-mvc/src/models/Investment.js
import { v4 as uuidv4 } from 'uuid';
import { investments } from '../database/data.js';
function create({ name, value }) {
const id = uuidv4();
const investment = { name, value, id };
if (name && value) {
investments.push(investment);
return investment;
} else {
throw new Error('Unable to create investment');
}
}
function read(field, value) {
if (field && value) {
const filteredInvestments = investments.filter((investment) =>
investment[field].includes(value)
);
return filteredInvestments;
}
return investments;
}
function readById(id) {
if (id) {
const index = investments.findIndex((investment) => investment.id === id);
if (!investments[index]) {
throw new Error('Investment not found');
}
return investments[index];
} else {
throw new Error('Unable to find investment');
}
}
function update({ id, name, value }) {
if (name && value && id) {
const newInvestment = { name, value, id };
const index = investments.findIndex((investment) => investment.id === id);
if (!investments[index]) {
throw new Error('Investment not found');
}
investments[index] = newInvestment;
return newInvestment;
} else {
throw new Error('Unable to update investment');
}
}
function remove(id) {
if (id) {
const index = investments.findIndex((investment) => investment.id === id);
investments.splice(index, 1);
return true;
} else {
throw new Error('Investment not found');
}
}
export default { create, read, readById, update, remove };
Seed
/codes/expressjs/invest-app-mvc/src/database/seeders.json
{
"investments": [
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"name": "Tesouro Selic 2029",
"value": 1000
},
{
"id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"name": "Tesouro Selic 2029",
"value": 500
}
]
}
/codes/expressjs/invest-app-mvc/src/database/seeders.json
{
"investments": [
{
"id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"name": "Tesouro Selic 2029",
"value": 1000
},
{
"id": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed",
"name": "Tesouro Selic 2029",
"value": 500
}
]
}
/codes/expressjs/invest-app-mvc/src/database/seeders.js
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
import Investment from '../models/Investment.js';
async function up() {
const file = resolve('src', 'database', 'seeders.json');
const seed = JSON.parse(readFileSync(file));
for (const investment of seed.investments) {
await Investment.create(investment);
}
}
export default { up };
/codes/expressjs/invest-app-mvc/src/database/seeders.js
import { resolve } from 'node:path';
import { readFileSync } from 'node:fs';
import Investment from '../models/Investment.js';
async function up() {
const file = resolve('src', 'database', 'seeders.json');
const seed = JSON.parse(readFileSync(file));
for (const investment of seed.investments) {
await Investment.create(investment);
}
}
export default { up };
Loader
/codes/expressjs/invest-app-mvc/src/index.js
import 'express-async-errors';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
import Seed from './database/seeders.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(express.static('public'));
server.use('/api', router);
await Seed.up();
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
/codes/expressjs/invest-app-mvc/src/index.js
import 'express-async-errors';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
import Seed from './database/seeders.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(express.static('public'));
server.use('/api', router);
await Seed.up();
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
Router
/codes/expressjs/invest-app-mvc/src/routes.js
import express from 'express';
import Investment from './models/Investment.js';
class HTTPError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/investments', async (req, res) => {
try {
const investment = req.body;
const createdInvestment = await Investment.create(investment);
return res.json(createdInvestment);
} catch (error) {
throw new HTTPError('Unable to create investment', 400);
}
});
router.get('/investments', async (req, res) => {
try {
const { name } = req.query;
const investments = await Investment.read('name', name);
res.json(investments);
} catch (error) {
throw new HTTPError('Unable to read investments', 400);
}
});
router.get('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = await Investment.readById(id);
res.json(investment);
} catch (error) {
throw new HTTPError('Unable to find investment', 400);
}
});
router.put('/investments/:id', async (req, res) => {
try {
const investment = req.body;
const id = req.params.id;
const updatedInvestment = await Investment.update({ ...investment, id });
return res.json(updatedInvestment);
} catch (error) {
throw new HTTPError('Unable to update investment', 400);
}
});
router.delete('/investments/:id', async (req, res) => {
const id = req.params.id;
if (await Investment.remove(id)) {
res.sendStatus(204);
} else {
throw new HTTPError('Unable to remove investment', 400);
}
});
// 404 handler
router.use((req, res, next) => {
res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.stack);
if (err instanceof HTTPError) {
res.status(err.code).json({ message: err.message });
} else {
res.status(500).json({ message: 'Something broke!' });
}
});
export default router;
/codes/expressjs/invest-app-mvc/src/routes.js
import express from 'express';
import Investment from './models/Investment.js';
class HTTPError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/investments', async (req, res) => {
try {
const investment = req.body;
const createdInvestment = await Investment.create(investment);
return res.json(createdInvestment);
} catch (error) {
throw new HTTPError('Unable to create investment', 400);
}
});
router.get('/investments', async (req, res) => {
try {
const { name } = req.query;
const investments = await Investment.read('name', name);
res.json(investments);
} catch (error) {
throw new HTTPError('Unable to read investments', 400);
}
});
router.get('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = await Investment.readById(id);
res.json(investment);
} catch (error) {
throw new HTTPError('Unable to find investment', 400);
}
});
router.put('/investments/:id', async (req, res) => {
try {
const investment = req.body;
const id = req.params.id;
const updatedInvestment = await Investment.update({ ...investment, id });
return res.json(updatedInvestment);
} catch (error) {
throw new HTTPError('Unable to update investment', 400);
}
});
router.delete('/investments/:id', async (req, res) => {
const id = req.params.id;
if (await Investment.remove(id)) {
res.sendStatus(204);
} else {
throw new HTTPError('Unable to remove investment', 400);
}
});
// 404 handler
router.use((req, res, next) => {
res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.stack);
if (err instanceof HTTPError) {
res.status(err.code).json({ message: err.message });
} else {
res.status(500).json({ message: 'Something broke!' });
}
});
export default router;