Refactor monolithic modules and harden booking, email, and auth infrastructure.

Split oversized frontend API client, email service, and admin/booking pages into focused modules while preserving import surfaces, and add Redis-backed queues, stale booking cleanup, stronger auth, and scale deployment configs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michilis
2026-06-25 07:12:59 +00:00
co-authored by Cursor
parent f0e2de2834
commit 613bd7be1d
75 changed files with 7702 additions and 5580 deletions
+31 -6
View File
@@ -25,6 +25,9 @@ import legalSettingsRoutes from './routes/legal-settings.js';
import faqRoutes from './routes/faq.js';
import emailService from './lib/email.js';
import { initEmailQueue } from './lib/emailQueue.js';
import { startBookingCleanup } from './lib/bookingCleanup.js';
import { getLock } from './lib/stores/lock.js';
import { describeBackends, describeRedis, logSelectedBackends } from './lib/backends.js';
const app = new Hono();
@@ -1870,9 +1873,16 @@ app.use('/uploads/*', async (c, next) => {
});
app.use('/uploads/*', serveStatic({ root: './' }));
// Health check
// Health check.
// Always returns 200 so a transient Redis blip does not cause the load balancer
// to pull a node; Redis/subsystem status is reported in the body for monitoring.
app.get('/health', (c) => {
return c.json({ status: 'ok', timestamp: new Date().toISOString() });
return c.json({
status: 'ok',
timestamp: new Date().toISOString(),
redis: describeRedis(),
backends: describeBackends(),
});
});
// API Routes
@@ -1909,15 +1919,30 @@ const port = parseInt(process.env.PORT || '3001');
// Initialize email queue with the email service reference
initEmailQueue(emailService);
// Initialize email templates on startup
emailService.seedDefaultTemplates().catch(err => {
console.error('[Email] Failed to seed templates:', err);
});
// Periodically expire abandoned pending bookings so they stop holding seats.
startBookingCleanup();
// Initialize email templates on startup.
// Guarded by a distributed lock so that, when running multiple replicas, only
// one instance seeds/updates templates per boot instead of all of them racing.
getLock()
.withLock('seed-templates', 30_000, () => emailService.seedDefaultTemplates())
.then((result) => {
if (result === null) {
console.log('[Email] Template seeding skipped (another instance holds the lock)');
}
})
.catch(err => {
console.error('[Email] Failed to seed templates:', err);
});
console.log(`🚀 Spanglish API server starting on port ${port}`);
console.log(`📚 API docs available at http://localhost:${port}/api-docs`);
console.log(`📋 OpenAPI spec at http://localhost:${port}/openapi.json`);
// Log which backend (memory/redis, local/s3) each subsystem selected.
logSelectedBackends();
serve({
fetch: app.fetch,
port,