"name": "express-parser",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon ./bin/www"
},
"dependencies":
{
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"twig": "~0.10.3",
"nodemon": "^2.0.22",
"dotenv": "^16.0.3",
"mongodb": "^5.2.0"
}
}
Express и Mongoose
const mongoose = require("mongoose");
const express = require("express");
const Schema = mongoose.Schema;
const app = express();
const jsonParser = express.json();
const userScheme = new Schema({name: String, age: Number}, {versionKey: false});
const User = mongoose.model("User", userScheme);
app.use(express.static(__dirname + "/public"));
async function main() {
try{
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
app.listen(3000);
console.log("Сервер ожидает подключения...");
}
catch(err) {
return console.log(err);
}
}
app.get("/api/users", async (req, res)=>{
// получаем всех пользователей
const users = await User.find({});
res.send(users);
});
app.get("/api/users/:id", async(req, res)=>{
const id = req.params.id;
// получаем одного пользователя по id
const user = await User.findById(id);
if(user) res.send(user);
else res.sendStatus(404);
});
app.post("/api/users", jsonParser, async (req, res) =>{
if(!req.body) return res.sendStatus(400);
const userName = req.body.name;
const userAge = req.body.age;
const user = new User({name: userName, age: userAge});
// сохраняем в бд
await user.save();
res.send(user);
});
app.delete("/api/users/:id", async(req, res)=>{
const id = req.params.id;
// удаляем по id
const user = await User.findByIdAndDelete(id);
if(user) res.send(user);
else res.sendStatus(404);
});
app.put("/api/users", jsonParser, async (req, res)=>{
if(!req.body) return res.sendStatus(400);
const id = req.body.id;
const userName = req.body.name;
const userAge = req.body.age;
const newUser = {age: userAge, name: userName};
// обновляем данные пользователя по id
const user = await User.findOneAndUpdate({_id: id}, newUser, {new: true});
if(user) res.send(user);
else res.sendStatus(404);
});
main();
// прослушиваем прерывание работы программы (ctrl-c)
process.on("SIGINT", async() => {
await mongoose.disconnect();
console.log("Приложение завершило работу");
process.exit();
});
Валидация
Mongoose имеет ряд встроенных правил валидации, которые мы можем указать в схеме:
required: требует обязательного наличия значения для свойства
min и max: задают минимальное и максимальное значения для числовых данных
minlength и maxlength: задают минимальную и максимальную длину для строк
enum: строка должна представлять одно из значений в указанном массиве строк
match: строка должна соответствовать регулярному выражению
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// установка схемы
const userScheme = new Schema({
name: {
type: String,
required: true,
minlength:3,
maxlength:20
},
age: {
type: Number,
default: 22,
required: true,
min: 1,
max:100
}
});
const User = mongoose.model("User", userScheme);
const user = new User({name: "Li"});
async function main() {
await mongoose.connect("mongodb://127.0.0.1:27017/usersdb");
await user.save();
console.log("Сохранен объект", user);
}
main().catch(console.log).finally(async()=>await mongoose.disconnect());
Index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Список пользователей</title>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<h2>Список пользователей</h2>
<form name="userForm">
<input type="hidden" name="id" value="0" />
<div class="form-group">
<label for="name">Имя:</label>
<input class="form-control" name="name" />
</div>
<div class="form-group">
<label for="age">Возраст:</label>
<input class="form-control" name="age" />
</div>
<div class="panel-body">
<button type="submit" class="btn btn-sm btn-primary">Сохранить</button>
<a id="reset" class="btn btn-sm btn-primary">Сбросить</a>
</div>
</form>
<table class="table table-condensed table-striped table-bordered">
<thead><tr><th>Id</th><th>Имя</th><th>возраст</th><th></th></tr></thead>
<tbody>
</tbody>
</table>
<script>
// Получение всех пользователей
async function getUsers() {
// отправляет запрос и получаем ответ
const response = await fetch("/api/users", {
method: "GET",
headers: { "Accept": "application/json" }
});
// если запрос прошел нормально
if (response.ok === true) {
// получаем данные
const users = await response.json();
let rows = document.querySelector("tbody");
users.forEach(user => {
// добавляем полученные элементы в таблицу
rows.append(row(user));
});
}
}
// Получение одного пользователя
async function getUser(id) {
const response = await fetch("/api/users/" + id, {
method: "GET",
headers: { "Accept": "application/json" }
});
if (response.ok === true) {
const user = await response.json();
const form = document.forms["userForm"];
form.elements["id"].value = user._id;
form.elements["name"].value = user.name;
form.elements["age"].value = user.age;
}
}
// Добавление пользователя
async function createUser(userName, userAge) {
const response = await fetch("api/users", {
method: "POST",
headers: { "Accept": "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
name: userName,
age: parseInt(userAge, 10)
})
});
if (response.ok === true) {
const user = await response.json();
reset();
document.querySelector("tbody").append(row(user));
}
}
// Изменение пользователя
async function editUser(userId, userName, userAge) {
const response = await fetch("api/users", {
method: "PUT",
headers: { "Accept": "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
id: userId,
name: userName,
age: parseInt(userAge, 10)
})
});
if (response.ok === true) {
const user = await response.json();
reset();
document.querySelector(`tr[data-rowid='${user._id}']`).replaceWith(row(user));
}
}
// Удаление пользователя
async function deleteUser(id) {
const response = await fetch("/api/users/" + id, {
method: "DELETE",
headers: { "Accept": "application/json" }
});
if (response.ok === true) {
const user = await response.json();
document.querySelector(`tr[data-rowid='${user._id}']`).remove();
}
}
// сброс формы
function reset() {
const form = document.forms["userForm"];
form.reset();
form.elements["id"].value = 0;
}
// создание строки для таблицы
function row(user) {
const tr = document.createElement("tr");
tr.setAttribute("data-rowid", user._id);
const idTd = document.createElement("td");
idTd.append(user._id);
tr.append(idTd);
const nameTd = document.createElement("td");
nameTd.append(user.name);
tr.append(nameTd);
const ageTd = document.createElement("td");
ageTd.append(user.age);
tr.append(ageTd);
const linksTd = document.createElement("td");
const editLink = document.createElement("a");
editLink.setAttribute("data-id", user._id);
editLink.setAttribute("style", "cursor:pointer;padding:15px;");
editLink.append("Изменить");
editLink.addEventListener("click", e => {
e.preventDefault();
getUser(user._id);
});
linksTd.append(editLink);
const removeLink = document.createElement("a");
removeLink.setAttribute("data-id", user._id);
removeLink.setAttribute("style", "cursor:pointer;padding:15px;");
removeLink.append("Удалить");
removeLink.addEventListener("click", e => {
e.preventDefault();
deleteUser(user._id);
});
linksTd.append(removeLink);
tr.appendChild(linksTd);
return tr;
}
// сброс значений формы
document.getElementById("reset").addEventListener("click", e => {
e.preventDefault();
reset();
})
// отправка формы
document.forms["userForm"].addEventListener("submit", e => {
e.preventDefault();
const form = document.forms["userForm"];
const id = form.elements["id"].value;
const name = form.elements["name"].value;
const age = form.elements["age"].value;
if (id == 0)
createUser(name, age);
else
editUser(id, name, age);
});
// загрузка пользователей
getUsers();
</script>
</body>
</html>