File size: 2,210 Bytes
aaef3a5
69ff6ba
 
 
 
 
 
 
 
8b8b6f5
69ff6ba
 
8b8b6f5
69ff6ba
aaef3a5
8b8b6f5
69ff6ba
 
aaef3a5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69ff6ba
 
8b8b6f5
69ff6ba
 
 
 
aaef3a5
 
69ff6ba
 
 
 
 
 
 
 
8b8b6f5
aaef3a5
69ff6ba
8b8b6f5
69ff6ba
 
 
8b8b6f5
 
69ff6ba
8b8b6f5
aaef3a5
69ff6ba
 
8b8b6f5
aaef3a5
69ff6ba
 
 
 
 
aaef3a5
69ff6ba
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// backend/src/server.js
import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import morgan from 'morgan';
import mongoose from 'mongoose';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const MONGODB_URI = process.env.MONGODB_URI;
const PORT = Number(process.env.PORT) || 7860;

const app = express();
app.set('trust proxy', 1);

// βœ… Allow embedding in Hugging Face iframe
app.use(
  helmet({
    // HF embeds your app in an iframe; disable frameguard so it can load.
    frameguard: false,

    // Keep CSP off unless you author a custom policy that permits hf.co ↔ hf.space.
    contentSecurityPolicy: false,

    // These can block some asset loads; relax for SPA builds.
    crossOriginEmbedderPolicy: false,
    crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' },
  })
);

app.use(
  cors({
    origin: true, // reflect request origin
    credentials: true,
  })
);
app.use(express.json({ limit: '1mb' }));
app.use(morgan('tiny'));

if (!MONGODB_URI) {
  console.error('❌ Missing MONGODB_URI environment variable.');
  process.exit(1);
}

// Mongo
mongoose.set('strictQuery', true);
try {
  await mongoose.connect(MONGODB_URI);
  console.log('βœ… MongoDB connected');
} catch (err) {
  console.error('❌ MongoDB connection error:', err.message || err);
  process.exit(1);
}

// Routes
import productsRouter from './routes/products.routes.js';

app.get('/health', (_req, res) => {
  const conn = mongoose.connection.readyState === 1 ? 'connected' : 'disconnected';
  res.json({ ok: conn === 'connected', db: conn });
});

app.use('/api/products', productsRouter);

// Static frontend
const clientDir = path.join(__dirname, '../../frontend/dist');
app.use(express.static(clientDir));

// SPA fallback (but not for /api/*)
app.get('*', (req, res) => {
  if (req.path.startsWith('/api/')) return res.status(404).json({ error: 'Not found' });
  res.sendFile(path.join(clientDir, 'index.html'));
});

// Start
app.listen(PORT, '0.0.0.0', () => {
  console.log(`πŸš€ API running on http://0.0.0.0:${PORT}`);
});