mirror of
https://github.com/microsoft/Web-Dev-For-Beginners.git
synced 2025-08-30 01:50:19 +02:00
folder names
This commit is contained in:
13
7-bank-project/api/.eslintrc.json
Normal file
13
7-bank-project/api/.eslintrc.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"env": {
|
||||
"commonjs": true,
|
||||
"es2020": true,
|
||||
"node": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 11
|
||||
},
|
||||
"rules": {
|
||||
}
|
||||
}
|
4
7-bank-project/api/.gitignore
vendored
Normal file
4
7-bank-project/api/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
*.logs
|
||||
.DS_Store
|
||||
.Thumbs.db
|
21
7-bank-project/api/LICENSE
Normal file
21
7-bank-project/api/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2020 Yohan Lasorsa (@sinedied)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
33
7-bank-project/api/README.md
Normal file
33
7-bank-project/api/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Bank API
|
||||
|
||||
> Bank API built with [Node.js](https://nodejs.org) + [Express](https://expressjs.com/).
|
||||
|
||||
The API is already built for you and not part of the exercise.
|
||||
|
||||
However, if you're interested to learn how to build an API like this you can follow this series of videos: https://aka.ms/NodeBeginner (videos 17 through 21 covers this exact API).
|
||||
|
||||
You can also take a look at this interactive tutorial: https://aka.ms/learn/express-api
|
||||
|
||||
## Running the server
|
||||
|
||||
Make sure you have [Node.js](https://nodejs.org) installed.
|
||||
|
||||
1. Git clone this repo.
|
||||
2. Open a terminal in `api` folder, then run `npm install`.
|
||||
3. Run `npm start`.
|
||||
|
||||
The server should start listening on port `5000`.
|
||||
|
||||
> Note: all entries are stored in-memory and are not persisted, so when the server is stopped all data is lost.
|
||||
|
||||
## API details
|
||||
|
||||
Route | Description
|
||||
---------------------------------------------|------------------------------------
|
||||
GET /api/ | Get server info
|
||||
POST /api/accounts/ | Create an account, ex: `{ user: 'Yohan', description: 'My budget', currency: 'EUR', balance: 100 }`
|
||||
GET /api/accounts/:user | Get all data for the specified account
|
||||
DELETE /api/accounts/:user | Remove specified account
|
||||
POST /api/accounts/:user/transactions | Add a transaction, ex: `{ date: '2020-07-23T18:25:43.511Z', object: 'Bought a book', amount: -20 }`
|
||||
DELETE /api/accounts/:user/transactions/:id | Remove specified transaction
|
||||
|
34
7-bank-project/api/api.http
Normal file
34
7-bank-project/api/api.http
Normal file
@@ -0,0 +1,34 @@
|
||||
# You need REST Client extension for VS Code to use this file
|
||||
# Download at https://aka.ms/vscode/rest-client
|
||||
|
||||
GET http://localhost:5000/api/
|
||||
|
||||
###
|
||||
|
||||
POST http://localhost:5000/api/accounts/
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
user=sinedied¤cy=$&balance=50
|
||||
|
||||
###
|
||||
|
||||
GET http://localhost:5000/api/accounts/sinedied
|
||||
|
||||
###
|
||||
|
||||
DELETE http://localhost:5000/api/accounts/sinedied
|
||||
|
||||
###
|
||||
|
||||
POST http://localhost:5000/api/accounts/sinedied/transactions
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"date": "2020-07-24T11:09:17.781Z",
|
||||
"object": "Bought book",
|
||||
"amount": -20
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
DELETE http://localhost:5000/api/accounts/sinedied/transactions/8825ff3e8331277911174fd1b73ff889
|
1313
7-bank-project/api/package-lock.json
generated
Normal file
1313
7-bank-project/api/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
7-bank-project/api/package.json
Normal file
30
7-bank-project/api/package.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "bank-api",
|
||||
"version": "1.0.0",
|
||||
"description": "Bank API",
|
||||
"private": true,
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"lint": "eslint",
|
||||
"format": "prettier --single-quote --write *.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": {
|
||||
"name": "Yohan Lasorsa",
|
||||
"url": "https://twitter.com/sinedied"
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"eslint": "^7.5.0",
|
||||
"prettier": "^2.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
197
7-bank-project/api/server.js
Normal file
197
7-bank-project/api/server.js
Normal file
@@ -0,0 +1,197 @@
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const cors = require('cors')
|
||||
const crypto = require('crypto');
|
||||
const pkg = require('./package.json');
|
||||
|
||||
// App constants
|
||||
const port = process.env.PORT || 5000;
|
||||
const apiPrefix = '/api';
|
||||
|
||||
// Store data in-memory, not suited for production use!
|
||||
const db = {
|
||||
test: {
|
||||
user: 'test',
|
||||
currency: '$',
|
||||
description: `Test account`,
|
||||
balance: 75,
|
||||
transactions: [
|
||||
{ id: '1', date: '2020-10-01', object: 'Pocket money', amount: 50 },
|
||||
{ id: '2', date: '2020-10-03', object: 'Book', amount: -10 },
|
||||
{ id: '3', date: '2020-10-04', object: 'Sandwich', amount: -5 }
|
||||
],
|
||||
}
|
||||
};
|
||||
|
||||
// Create the Express app & setup middlewares
|
||||
const app = express();
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(cors({ origin: /http:\/\/localhost/ }));
|
||||
app.options('*', cors());
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
// Configure routes
|
||||
const router = express.Router();
|
||||
|
||||
// Get server infos
|
||||
router.get('/', (req, res) => {
|
||||
return res.send(`${pkg.description} v${pkg.version}`);
|
||||
});
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// Create an account
|
||||
router.post('/accounts', (req, res) => {
|
||||
// Check mandatory request parameters
|
||||
if (!req.body.user || !req.body.currency) {
|
||||
return res.status(400).json({ error: 'Missing parameters' });
|
||||
}
|
||||
|
||||
// Check if account already exists
|
||||
if (db[req.body.user]) {
|
||||
return res.status(409).json({ error: 'User already exists' });
|
||||
}
|
||||
|
||||
// Convert balance to number if needed
|
||||
let balance = req.body.balance;
|
||||
if (balance && typeof balance !== 'number') {
|
||||
balance = parseFloat(balance);
|
||||
if (isNaN(balance)) {
|
||||
return res.status(400).json({ error: 'Balance must be a number' });
|
||||
}
|
||||
}
|
||||
|
||||
// Create account
|
||||
const account = {
|
||||
user: req.body.user,
|
||||
currency: req.body.currency,
|
||||
description: req.body.description || `${req.body.user}'s budget`,
|
||||
balance: balance || 0,
|
||||
transactions: [],
|
||||
};
|
||||
db[req.body.user] = account;
|
||||
|
||||
return res.status(201).json(account);
|
||||
});
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// Get all data for the specified account
|
||||
router.get('/accounts/:user', (req, res) => {
|
||||
const account = db[req.params.user];
|
||||
|
||||
// Check if account exists
|
||||
if (!account) {
|
||||
return res.status(404).json({ error: 'User does not exist' });
|
||||
}
|
||||
|
||||
return res.json(account);
|
||||
});
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// Remove specified account
|
||||
router.delete('/accounts/:user', (req, res) => {
|
||||
const account = db[req.params.user];
|
||||
|
||||
// Check if account exists
|
||||
if (!account) {
|
||||
return res.status(404).json({ error: 'User does not exist' });
|
||||
}
|
||||
|
||||
// Removed account
|
||||
delete db[req.params.user];
|
||||
|
||||
res.sendStatus(204);
|
||||
});
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// Add a transaction to a specific account
|
||||
router.post('/accounts/:user/transactions', (req, res) => {
|
||||
const account = db[req.params.user];
|
||||
|
||||
// Check if account exists
|
||||
if (!account) {
|
||||
return res.status(404).json({ error: 'User does not exist' });
|
||||
}
|
||||
|
||||
// Check mandatory requests parameters
|
||||
if (!req.body.date || !req.body.object || !req.body.amount) {
|
||||
return res.status(400).json({ error: 'Missing parameters' });
|
||||
}
|
||||
|
||||
// Convert amount to number if needed
|
||||
let amount = req.body.amount;
|
||||
if (amount && typeof amount !== 'number') {
|
||||
amount = parseFloat(amount);
|
||||
}
|
||||
|
||||
// Check that amount is a valid number
|
||||
if (amount && isNaN(amount)) {
|
||||
return res.status(400).json({ error: 'Amount must be a number' });
|
||||
}
|
||||
|
||||
// Generates an ID for the transaction
|
||||
const id = crypto
|
||||
.createHash('md5')
|
||||
.update(req.body.date + req.body.object + req.body.amount)
|
||||
.digest('hex');
|
||||
|
||||
// Check that transaction does not already exist
|
||||
if (account.transactions.some((transaction) => transaction.id === id)) {
|
||||
return res.status(409).json({ error: 'Transaction already exists' });
|
||||
}
|
||||
|
||||
// Add transaction
|
||||
const transaction = {
|
||||
id,
|
||||
date: req.body.date,
|
||||
object: req.body.object,
|
||||
amount,
|
||||
};
|
||||
account.transactions.push(transaction);
|
||||
|
||||
// Update balance
|
||||
account.balance += transaction.amount;
|
||||
|
||||
return res.status(201).json(transaction);
|
||||
});
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
// Remove specified transaction from account
|
||||
router.delete('/accounts/:user/transactions/:id', (req, res) => {
|
||||
const account = db[req.params.user];
|
||||
|
||||
// Check if account exists
|
||||
if (!account) {
|
||||
return res.status(404).json({ error: 'User does not exist' });
|
||||
}
|
||||
|
||||
const transactionIndex = account.transactions.findIndex(
|
||||
(transaction) => transaction.id === req.params.id
|
||||
);
|
||||
|
||||
// Check if transaction exists
|
||||
if (transactionIndex === -1) {
|
||||
return res.status(404).json({ error: 'Transaction does not exist' });
|
||||
}
|
||||
|
||||
// Remove transaction
|
||||
account.transactions.splice(transactionIndex, 1);
|
||||
|
||||
res.sendStatus(204);
|
||||
});
|
||||
|
||||
// ***************************************************************************
|
||||
|
||||
// Add 'api` prefix to all routes
|
||||
app.use(apiPrefix, router);
|
||||
|
||||
// Start the server
|
||||
app.listen(port, () => {
|
||||
console.log(`Server listening on port ${port}`);
|
||||
});
|
32
7-bank-project/api/translations/README.es.md
Normal file
32
7-bank-project/api/translations/README.es.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# API bancaria
|
||||
|
||||
> API bancaria construida con [Node.js](https://nodejs.org) + [Express](https://expressjs.com/).
|
||||
|
||||
La API ya está creada para usted y no forma parte del ejercicio.
|
||||
|
||||
Sin embargo, si está interesado en aprender cómo construir una API como esta, puede seguir esta serie de videos: https://aka.ms/NodeBeginner (los videos 17 a 21 cubren esta API exacta).
|
||||
|
||||
También puede echar un vistazo a este tutorial interactivo: https://aka.ms/learn/express-api
|
||||
|
||||
## Ejecutando el servidor
|
||||
|
||||
Asegúrese de tener [Node.js](https://nodejs.org) instalado.
|
||||
|
||||
1. Git clone este repositorio.
|
||||
2. Abra una terminal en la carpeta `api`, luego ejecute `npm install`.
|
||||
3. Ejecute `npm start`.
|
||||
|
||||
El servidor debería comenzar a escuchar en el puerto `5000`.
|
||||
|
||||
> Nota: todas las entradas se almacenan en la memoria y no se conservan, por lo que cuando se detiene el servidor, se pierden todos los datos.
|
||||
|
||||
## API
|
||||
|
||||
Ruta | Descripción
|
||||
---------------------------------------------|------------------------------------
|
||||
GET /api/ | Obtener información del servidor
|
||||
POST /api/accounts/ | Cree una cuenta, por ejemplo: `{ user: 'Yohan', description: 'My budget', currency: 'EUR', balance: 100 }`
|
||||
GET /api/accounts/:user | Obtener todos los datos de la cuenta especificada
|
||||
DELETE /api/accounts/:user | Eliminar cuenta especificada
|
||||
POST /api/accounts/:user/transactions | Agregar una transacción, por ejemplo: `{ date: '2020-07-23T18:25:43.511Z', object: 'Bought a book', amount: -20 }`
|
||||
DELETE /api/accounts/:user/transactions/:id | Eliminar transacción especificada
|
Reference in New Issue
Block a user