File: //srv/rmgun_admin/admin-next/express/src/index.ts
import express, { Express, Request, Response } from 'express';
import cors from 'cors';
import helmet from 'helmet';
import dotenv from 'dotenv';
import cron from 'node-cron';
import * as path from 'path';
import * as fs from 'fs';
import { initializeFirebase } from './config/firebase';
import { CsvExportService } from './services/csv-export-service';
import { EmailService } from './services/email-service';
import { RegistrationService } from './services/registration-service';
import testRouter from './routes/test';
// Load .env from parent directory (shared with Next.js)
dotenv.config({ path: path.join(__dirname, '../../.env') });
const app: Express = express();
const PORT = process.env.PORT || 4000;
// Initialize Firebase
try {
initializeFirebase();
} catch (error) {
console.error('Failed to initialize Firebase. Service will continue without Firestore access.');
}
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get('/health', (_req: Request, res: Response) => {
res.status(200).json({
status: 'healthy',
uptime: process.uptime(),
timestamp: new Date().toISOString(),
schedulerEnabled: process.env.SCHEDULER_ENABLED === 'true'
});
});
app.get('/', (_req: Request, res: Response) => {
res.json({
message: 'Express service is running',
version: '1.0.0',
features: {
scheduler: process.env.SCHEDULER_ENABLED === 'true',
weeklyExport: true
}
});
});
// Manual export endpoint with optional email sending
app.get('/export/weekly', async (req: Request, res: Response) => {
try {
const sendEmail = req.query.email !== 'false'; // Default to true
const filepath = await CsvExportService.exportWeeklyRegistrations();
if (filepath) {
let emailSent = false;
if (sendEmail) {
const registrations = await RegistrationService.getWeeklyRegistrations();
emailSent = await EmailService.sendWeeklyExport(filepath, registrations.length);
}
res.json({
success: true,
message: 'Weekly export completed',
file: path.basename(filepath),
emailSent
});
} else {
res.json({
success: false,
message: 'No registrations found for export'
});
}
} catch (error) {
console.error('Export error:', error);
res.status(500).json({
success: false,
error: 'Failed to export registrations'
});
}
});
// List exported files
app.get('/export/list', (_req: Request, res: Response) => {
const files = CsvExportService.getExportedFiles();
res.json({
files,
count: files.length
});
});
// Download exported file
app.get('/export/download/:filename', (req: Request, res: Response): void => {
const filename = req.params.filename;
const filepath = path.join(__dirname, '../exports', filename);
if (!fs.existsSync(filepath)) {
res.status(404).json({ error: 'File not found' });
return;
}
res.download(filepath);
});
// Mount test routes (only in development/test environments)
if (process.env.NODE_ENV !== 'production') {
app.use('/test', testRouter);
console.log('๐งช Test routes enabled at /test/*');
}
// Scheduler setup
if (process.env.SCHEDULER_ENABLED === 'true') {
const timezone = process.env.SCHEDULER_TIMEZONE || 'Europe/Warsaw';
// Weekly export - Every Sunday at 22:00
cron.schedule('0 22 * * 0', async () => {
console.log('๐ Starting weekly CSV export with email (Sunday 22:00)');
try {
const filepath = await CsvExportService.exportWeeklyRegistrations();
if (filepath) {
console.log(`โ
Weekly export completed: ${path.basename(filepath)}`);
// Send email with CSV attachment
const registrations = await RegistrationService.getWeeklyRegistrations();
const emailSent = await EmailService.sendWeeklyExport(filepath, registrations.length);
if (emailSent) {
console.log('๐ง Weekly report email sent successfully');
} else {
console.log('โ ๏ธ Failed to send email or email disabled');
}
} else {
console.log('โ ๏ธ No registrations to export this week');
}
// Clean old exports (keep last 4 weeks)
await CsvExportService.cleanOldExports();
} catch (error) {
console.error('โ Weekly export failed:', error);
}
}, {
scheduled: true,
timezone
});
// Optional: Daily cleanup of old exports
cron.schedule('0 3 * * *', async () => {
console.log('๐งน Running daily cleanup of old exports');
try {
await CsvExportService.cleanOldExports();
} catch (error) {
console.error('Cleanup failed:', error);
}
}, {
scheduled: true,
timezone
});
console.log(`๐
Scheduler enabled with timezone: ${timezone}`);
console.log('โฐ Weekly export scheduled for Sunday 22:00');
}
app.listen(PORT, () => {
console.log(`โก๏ธ[server]: Express service is running at http://localhost:${PORT}`);
console.log(`โ๏ธ [environment]: ${process.env.NODE_ENV || 'development'}`);
console.log(`๐
[scheduler]: ${process.env.SCHEDULER_ENABLED === 'true' ? 'Enabled' : 'Disabled'}`);
console.log(`๐ [exports]: Available at /export/*`);
});