/** * Copyright (c) 2024-2026 Тарабанов Александр Викторович * All rights reserved. * * This software is proprietary and confidential. * Unauthorized copying, modification, or distribution is prohibited. * * For licensing inquiries: info@hb3-accelerator.com * Website: https://hb3-accelerator.com * GitHub: https://github.com/VC-HB3-Accelerator */ const fs = require('fs'); const path = require('path'); const http = require('http'); const https = require('https'); const { initDbPool, getQuery } = require('../db'); // URL бэкенда для запроса статей (тот же контейнер) const BACKEND_API_URL = process.env.BACKEND_API_URL || 'http://localhost:8000'; // Конфигурация // В Docker используем имя контейнера, локально - localhost const BASE_URL = process.env.PRERENDER_BASE_URL || process.env.FRONTEND_URL || (process.env.NODE_ENV === 'production' ? 'http://dapp-frontend:5173' : 'http://localhost:5173'); const OUTPUT_DIR = process.env.PRERENDER_OUTPUT_DIR || (process.env.NODE_ENV === 'production' ? '/app/frontend_dist/blog' : path.join(__dirname, '../../frontend/dist/blog')); // Путь к шаблону index.html фронтенда (для app-shell) const FRONTEND_INDEX_HTML = process.env.PRERENDER_INDEX_TEMPLATE || (process.env.NODE_ENV === 'production' ? '/app/frontend_dist/index.html' : path.join(__dirname, '../../frontend/dist/index.html')); const TIMEOUT = 30000; // 30 секунд на загрузку страницы /** * Загружает app-shell (index.html) по URL, если локальный файл недоступен (например на VDS нет frontend/dist). */ function fetchAppShellFromUrl(urlString) { return new Promise((resolve, reject) => { let url; try { url = new URL(urlString); } catch (e) { reject(new Error('Неверный URL для app-shell: ' + urlString)); return; } const mod = url.protocol === 'https:' ? https : http; const req = mod.request(url, { method: 'GET', timeout: 15000 }, (res) => { if (res.statusCode !== 200) { reject(new Error(`HTTP ${res.statusCode}`)); return; } const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => { try { resolve(Buffer.concat(chunks).toString('utf8')); } catch (e) { reject(e); } }); }); req.on('error', reject); req.on('timeout', () => { req.destroy(); reject(new Error('Timeout')); }); req.end(); }); } /** * Возвращает HTML app-shell: сначала из файла, при неудаче — по URL (PRERENDER_BASE_URL). */ async function getAppShellTemplate() { try { const html = fs.readFileSync(FRONTEND_INDEX_HTML, 'utf8'); if (html && html.includes('