Files
neomovies-api/src/index.js
Foxix b3f1ded394 Update 3 files
- /api/index.js
- /src/index.js
- /vercel.json
2025-01-03 20:14:34 +00:00

198 lines
6.3 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();
// Определяем базовый URL для документации
const BASE_URL = process.env.NODE_ENV === 'production'
? 'https://neomovies-api.vercel.app'
: 'http://localhost:3000';
// 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.NODE_ENV === 'production' ? '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: 'Сообщение об ошибке'
}
}
}
}
}
},
apis: [path.join(__dirname, 'routes', '*.js'), __filename]
};
const swaggerDocs = swaggerJsdoc(swaggerOptions);
// CORS configuration
app.use(cors({
origin: true,
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['X-Requested-With', 'Content-Type', 'Authorization', 'Accept']
}));
// Handle preflight requests
app.options('*', cors());
// Middleware
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// TMDB client middleware
app.use((req, res, next) => {
const token = process.env.TMDB_ACCESS_TOKEN || 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJkOWRlZTY5ZjYzNzYzOGU2MjY5OGZhZGY0ZjhhYTNkYyIsInN1YiI6IjY1OTVkNmM5ODY5ZTc1NzJmOTY1MjZiZiIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.Wd_tBYGkAoGPVHq3A5DwV1iLs_eGvH3RRz86ghJTmU8';
if (!token) {
return res.status(500).json({ error: 'TMDB_ACCESS_TOKEN is not set' });
}
req.tmdb = new TMDBClient(token);
next();
});
// API Documentation routes
app.get('/api-docs', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'api-docs', 'index.html'));
});
app.get('/api-docs/swagger.json', (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.send(swaggerDocs);
});
// API 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:
* type: object
* properties:
* status:
* type: string
* enum: [ok, error]
* tmdb:
* type: object
* properties:
* status:
* type: string
* enum: [ok, error]
*/
app.get('/health', async (req, res) => {
try {
const health = await healthCheck.getFullHealth(req.tmdb);
res.json(health);
} catch (error) {
res.status(500).json({
status: 'error',
error: error.message
});
}
});
// Error handling
app.use((err, req, res, next) => {
console.error('Error:', err);
res.status(500).json({
error: 'Internal Server Error',
message: process.env.NODE_ENV === 'development' ? err.message : undefined
});
});
// Handle 404
app.use((req, res) => {
res.status(404).json({ error: 'Not Found' });
});
// Export the Express API
module.exports = app;
// Start server only in development
if (process.env.NODE_ENV !== 'production') {
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
console.log(`Documentation available at http://localhost:${port}/api-docs`);
});
}