Files
neomovies-api/src/index.js
Foxix 6d2491b17c Update 10 files
- /package.json
- /package-lock.json
- /README.md
- /vercel.json
- /src/config/tmdb.js
- /src/public/api-docs/index.html
- /src/utils/date.js
- /src/utils/health.js
- /src/routes/movies.js
- /src/index.js
2025-01-03 19:46:10 +00:00

266 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const swaggerJsdoc = require('swagger-jsdoc');
const path = require('path');
const TMDBClient = require('./config/tmdb');
const healthCheck = require('./utils/health');
const app = express();
const port = process.env.PORT || 3000;
// Определяем базовый URL для документации
const BASE_URL = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: `http://localhost:${port}`;
// Swagger configuration
const swaggerOptions = {
definition: {
openapi: '3.0.0',
info: {
title: 'Neo Movies API',
version: '1.0.0',
description: 'API для поиска и получения информации о фильмах с поддержкой русского языка',
contact: {
name: 'API Support',
url: 'https://gitlab.com/foxixus/neomovies-api'
}
},
servers: [
{
url: BASE_URL,
description: process.env.VERCEL_URL ? 'Production server' : 'Development server',
},
],
tags: [
{
name: 'movies',
description: 'Операции с фильмами'
},
{
name: 'health',
description: 'Проверка работоспособности API'
}
],
components: {
schemas: {
Movie: {
type: 'object',
properties: {
id: {
type: 'integer',
description: 'ID фильма'
},
title: {
type: 'string',
description: 'Название фильма'
},
overview: {
type: 'string',
description: 'Описание фильма'
},
release_date: {
type: 'string',
format: 'date',
description: 'Дата выхода'
},
vote_average: {
type: 'number',
description: 'Средняя оценка'
},
poster_path: {
type: 'string',
description: 'URL постера'
},
backdrop_path: {
type: 'string',
description: 'URL фонового изображения'
}
}
},
Error: {
type: 'object',
properties: {
error: {
type: 'string',
description: 'Сообщение об ошибке'
}
}
},
Health: {
type: 'object',
properties: {
status: {
type: 'string',
enum: ['healthy', 'unhealthy'],
description: 'Общий статус API'
},
version: {
type: 'string',
description: 'Версия API'
},
uptime: {
type: 'object',
properties: {
seconds: {
type: 'integer',
description: 'Время работы в секундах'
},
formatted: {
type: 'string',
description: 'Отформатированное время работы'
}
}
},
tmdb: {
type: 'object',
properties: {
status: {
type: 'string',
enum: ['ok', 'error'],
description: 'Статус подключения к TMDB'
},
responseTime: {
type: 'integer',
description: 'Время ответа TMDB в мс'
},
error: {
type: 'string',
description: 'Сообщение об ошибке, если есть'
}
}
},
memory: {
type: 'object',
properties: {
heapTotal: {
type: 'integer',
description: 'Общий размер кучи (MB)'
},
heapUsed: {
type: 'integer',
description: 'Использованный размер кучи (MB)'
},
rss: {
type: 'integer',
description: 'Resident Set Size (MB)'
},
memoryUsage: {
type: 'integer',
description: 'Процент использования памяти'
},
system: {
type: 'object',
properties: {
total: {
type: 'integer',
description: 'Общая память системы (MB)'
},
free: {
type: 'integer',
description: 'Свободная память системы (MB)'
},
usage: {
type: 'integer',
description: 'Процент использования системной памяти'
}
}
}
}
},
system: {
type: 'object',
properties: {
platform: {
type: 'string',
description: 'Операционная система'
},
arch: {
type: 'string',
description: 'Архитектура процессора'
},
nodeVersion: {
type: 'string',
description: 'Версия Node.js'
},
cpuUsage: {
type: 'number',
description: 'Загрузка CPU'
}
}
},
timestamp: {
type: 'string',
format: 'date-time',
description: 'Время проверки'
}
}
}
}
}
},
apis: ['./src/routes/*.js', './src/index.js'],
};
const swaggerDocs = swaggerJsdoc(swaggerOptions);
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// TMDB client middleware
app.use((req, res, next) => {
if (!process.env.TMDB_ACCESS_TOKEN) {
return res.status(500).json({ error: 'TMDB_ACCESS_TOKEN is not set' });
}
req.tmdb = new TMDBClient(process.env.TMDB_ACCESS_TOKEN);
next();
});
// Serve Swagger JSON
app.get('/api-docs/swagger.json', (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.send(swaggerDocs);
});
// Routes
app.use('/movies', require('./routes/movies'));
/**
* @swagger
* /health:
* get:
* tags: [health]
* summary: Проверка работоспособности API
* description: Возвращает подробную информацию о состоянии API, включая статус TMDB, использование памяти и системную информацию
* responses:
* 200:
* description: API работает нормально
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Health'
*/
app.get('/health', async (req, res) => {
const health = await healthCheck.getFullHealth(req.tmdb);
res.json(health);
});
// Error handling
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
});
// Start server
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
console.log(`Documentation available at http://localhost:${port}/api-docs`);
});
app.get('/api-docs', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});