Привет, Хабр!
Сегодня мы продемонстрируем как создавать back-end приложения на Node.js c PostqreSQL. В качестве примера создадим простейший back-end на Node.js с использованием PostgreSQL.
Почему именно Node.js и PostgreSQL? Node.js имеет хорошую скорость и асинхронность, а PostgreSQL, в свою очередь, является мощной и надежной СУБД.
Вместе они создают идеальный тандем для создания качественных приложений.
Создание и настройка проекта
Все будем делать на Винде.
Установим
Node.Js
Переходим на официальный сайт Node.js и скачиваем установочный файл для Windows.
Далее запускаем установочный файл и следуйте инструкциям мастера установки.
Здесь еще важно, чтобы был выбран флажок для установки npm вместе с Node.js.
После завершения установки открываем командную строку и вводим node -v
и npm -v
, чтобы проверить успешность установки.
PostgreSQL
Скачиваем PostgreSQL с официального сайта. Установка там достаточна простая, но важно проверить, что включены pgAdmin и psql.
Далее создаем саму базы данных и юзера.
Открываем командную строку или терминал.
Входим в консоль PostgreSQL от имени суперпользователя (обычно postgres
):
sudo -i -u postgres
psql
Создаем новую БД:
CREATE DATABASE mydatabase;
Создайте нового пользователя с паролем:
CREATE USER myuser WITH ENCRYPTED PASSWORD 'qwerty';
Даем пользователю права на созданную БД:
GRANT ALL PRIVILEGES ON DATABASE mydatabase TO myuser;
Выходим из консоли PostgreSQL командой \q
.
Инициализация нового проекта Node.js
Создадим новую директорию для проекта:
mkdir my-node-project
cd my-node-project
Инициализируем проект с помощью npm:
npm init -y
Это создаст файл package.json
, который будет содержать основную инфу о проекте, включая зависимости и скрипты для запуска проекта.
Установим необходимые пакеты для работы с Express и PostgreSQL:
npm install express pg dotenv
Express: фреймворк для создания серверных приложений на Node.js.
pg: оф. клиент для PostgreSQL.
dotenv: для управления переменными окружения.
Организуем проект таким образом, чтобы было легко управлять и расширять его:
my-node-project/
│
├── src/
│ ├── routes/
│ │ └── index.js
│ ├── controllers/
│ │ └── userController.js
│ ├── models/
│ │ └── userModel.js
│ ├── config/
│ │ └── db.js
│ └── app.js
├── .env
├── package.json
└── README.md
routes: маршруты приложения.
controllers: логика обработки запросов.
models: модели базы данных.
config: конфиг, который включает настройки подключения к БД.
app.js: главный файл приложения.
Подключение к базе данных
Создадим файл конфигурации для подключения к БД, например, db.js
:
const { Pool } = require('pg');
require('dotenv').config();
const pool = new Pool({
user: process.env.DB_USER,
host: process.env.DB_HOST,
database: process.env.DB_NAME,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
});
module.exports = pool;
Добавляем переменные окружения в файл .env
:
DB_USER=yourusername
DB_HOST=localhost
DB_NAME=yourdatabase
DB_PASSWORD=yourpassword
DB_PORT=5432
Создаем тестовый запрос в app.js
, чтобы убедиться, что соединение с базой данных установлено:
const express = require('express');
const pool = require('./config/db');
const app = express();
pool.query('SELECT NOW()', (err, res) => {
if(err) {
console.error('Error connecting to the database', err.stack);
} else {
console.log('Connected to the database:', res.rows);
}
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Создание API с использованием Express
Создадим файл маршрутов index.js
и определим базовые маршруты:
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.get('/users', userController.getUsers);
router.post('/users', userController.createUser);
router.put('/users/:id', userController.updateUser);
router.delete('/users/:id', userController.deleteUser);
module.exports = router;
В контроллере userController.js
описываем логику взаимодействия с базой данных:
const pool = require('../config/db');
exports.getUsers = async (req, res) => {
try {
const result = await pool.query('SELECT * FROM users');
res.status(200).json(result.rows);
} catch (err) {
res.status(500).json({ error: err.message });
}
};
exports.createUser = async (req, res) => {
const { name, email } = req.body;
try {
const result = await pool.query('INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *', [name, email]);
res.status(201).json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
};
exports.updateUser = async (req, res) => {
const { id } = req.params;
const { name, email } = req.body;
try {
const result = await pool.query('UPDATE users SET name = $1, email = $2 WHERE id = $3 RETURNING *', [name, email, id]);
res.status(200).json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
};
exports.deleteUser = async (req, res) => {
const { id } = req.params;
try {
await pool.query('DELETE FROM users WHERE id = $1', [id]);
res.status(204).send();
} catch (err) {
res.status(500).json({ error: err.message });
}
};
Юзаем middleware для валидации данных и обработки ошибок:
const express = require('express');
const app = express();
const routes = require('./routes');
const { body, validationResult } = require('express-validator');
app.use(express.json());
app.post('/users',
body('email').isEmail(),
body('name').notEmpty(),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
next();
},
routes
);
app.use('/api', routes);
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
Тестирование и отладка
Теперь, когда API создан и подключен к базе данных, можно и нужно начинать откладывать и тестировать.
Postman хорошо справится с этой задачей.
Создаем запрос в Postman:
Запускаем Postman и создаем новый запрос.
Вводим URL API, например,
http://localhost:3000/api/users
.Выбираем метод запроса: GET, POST, PUT, DELETE.
Если запрос требует тела, например, POST или PUT, добавляемJSON-данные в разделе Body.
Отправка запроса и проверка ответа:
Нажимаем «Send» и проверяемответ в нижней части окна Postman
Можно реализовать логирование
Установим библиотеку winston
для логирования:
npm install winston
Создадим файл logger.js
для настройки логирования:
const { createLogger, format, transports } = require('winston');
const logger = createLogger({
level: 'info',
format: format.combine(
format.timestamp(),
format.json()
),
transports: [
new transports.Console(),
new transports.File({ filename: 'error.log', level: 'error' }),
new transports.File({ filename: 'combined.log' })
],
});
module.exports = logger;
Импортируем и используем логер в app.js
и других файлах:
const logger = require('./logger');
app.use((req, res, next) => {
logger.info(`${req.method} ${req.url}`);
next();
});
app.use((err, req, res, next) => {
logger.error(err.message);
res.status(500).send('Something broke!');
});
Теперь мы уже создали готовый и простейший back-end на Node.js с использованием PostgreSQL, а также подключили логирование и Postman. Кстати, сюда еще можно добавить модульное тестирование с помощью библиотеки Jest.
Cоздавать back-end на Node.js с использованием PostgreSQL позволяет воспользоваться всеми фичами этих технологий!
Всех желающих приглашаем на открытый урок по пользовательским типам данных в PostgreSQL, который пройдет 23 июля.
На этом открытом уроке расскажем о возможностях PostgreSQL в части создания собственных типов данных. Разберем, как можно создать пользовательский тип, как с ним работать и несколько примеров детально «до винтика».
Записаться на урок можно бесплатно по ссылке.