Spaces:
Running
Running
Delete server.js
Browse files
server.js
DELETED
|
@@ -1,141 +0,0 @@
|
|
| 1 |
-
import express from 'express';
|
| 2 |
-
import cors from 'cors';
|
| 3 |
-
import path from 'path';
|
| 4 |
-
import { fileURLToPath } from 'url';
|
| 5 |
-
import sqlite3 from 'sqlite3';
|
| 6 |
-
import bcrypt from 'bcryptjs';
|
| 7 |
-
|
| 8 |
-
const app = express();
|
| 9 |
-
const port = process.env.PORT || 7860;
|
| 10 |
-
|
| 11 |
-
// --- Database Initialization ---
|
| 12 |
-
const __filename = fileURLToPath(import.meta.url);
|
| 13 |
-
const __dirname = path.dirname(__filename);
|
| 14 |
-
const dbPath = path.join(__dirname, 'database.db');
|
| 15 |
-
const db = new sqlite3.Database(dbPath);
|
| 16 |
-
|
| 17 |
-
db.serialize(() => {
|
| 18 |
-
db.run(`
|
| 19 |
-
CREATE TABLE IF NOT EXISTS users (
|
| 20 |
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 21 |
-
username TEXT UNIQUE NOT NULL,
|
| 22 |
-
password_hash TEXT NOT NULL,
|
| 23 |
-
role TEXT DEFAULT 'Standard Node',
|
| 24 |
-
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
| 25 |
-
)
|
| 26 |
-
`);
|
| 27 |
-
db.run(`
|
| 28 |
-
CREATE TABLE IF NOT EXISTS messages (
|
| 29 |
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
| 30 |
-
user_id INTEGER,
|
| 31 |
-
role TEXT NOT NULL,
|
| 32 |
-
content TEXT NOT NULL,
|
| 33 |
-
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
|
| 34 |
-
FOREIGN KEY(user_id) REFERENCES users(id)
|
| 35 |
-
)
|
| 36 |
-
`);
|
| 37 |
-
});
|
| 38 |
-
|
| 39 |
-
let activeSession = null;
|
| 40 |
-
|
| 41 |
-
// Mock Citi Data
|
| 42 |
-
const CITI_ACCOUNTS = {
|
| 43 |
-
accountGroupDetails: [{
|
| 44 |
-
accountGroup: "CHECKING",
|
| 45 |
-
checkingAccountsDetails: [{
|
| 46 |
-
productName: "Corporate Mastery Checking",
|
| 47 |
-
accountNickname: "Main Ops Node",
|
| 48 |
-
accountDescription: "Corporate Mastery Checking - 9594",
|
| 49 |
-
balanceType: "ASSET",
|
| 50 |
-
displayAccountNumber: "XXXXXX9594",
|
| 51 |
-
accountId: "citi_acc_99201",
|
| 52 |
-
currencyCode: "USD",
|
| 53 |
-
accountStatus: "ACTIVE",
|
| 54 |
-
currentBalance: 1245000.50,
|
| 55 |
-
availableBalance: 1240000.00
|
| 56 |
-
}],
|
| 57 |
-
totalCurrentBalance: { localCurrencyCode: "USD", localCurrencyBalanceAmount: 1245000.50 },
|
| 58 |
-
totalAvailableBalance: { localCurrencyCode: "USD", localCurrencyBalanceAmount: 1240000.00 }
|
| 59 |
-
}],
|
| 60 |
-
customer: { customerId: "citi_cust_884102" }
|
| 61 |
-
};
|
| 62 |
-
|
| 63 |
-
app.use(cors());
|
| 64 |
-
app.use(express.json());
|
| 65 |
-
app.use(express.urlencoded({ extended: true }));
|
| 66 |
-
|
| 67 |
-
// Auth API
|
| 68 |
-
app.get('/api/auth/me', (req, res) => res.json({ isAuthenticated: !!activeSession, user: activeSession }));
|
| 69 |
-
app.post('/api/auth/login', (req, res) => {
|
| 70 |
-
const { username, password } = req.body;
|
| 71 |
-
db.get('SELECT * FROM users WHERE username = ?', [username], async (err, user) => {
|
| 72 |
-
if (err || !user) return res.status(401).json({ success: false, message: 'Invalid node' });
|
| 73 |
-
const match = await bcrypt.compare(password, user.password_hash);
|
| 74 |
-
if (match) {
|
| 75 |
-
activeSession = { id: `USR-${user.id}`, dbId: user.id, name: user.username, role: user.role, lastLogin: new Date().toISOString() };
|
| 76 |
-
res.json({ success: true, user: activeSession });
|
| 77 |
-
} else {
|
| 78 |
-
res.status(401).json({ success: false });
|
| 79 |
-
}
|
| 80 |
-
});
|
| 81 |
-
});
|
| 82 |
-
app.post('/api/auth/logout', (req, res) => { activeSession = null; res.json({ success: true }); });
|
| 83 |
-
|
| 84 |
-
// Gemini REST Proxy (Exact Implementation as per user's curl requirement)
|
| 85 |
-
app.post('/api/gemini/generate', async (req, res) => {
|
| 86 |
-
try {
|
| 87 |
-
// Hugging Face secrets are available via process.env
|
| 88 |
-
const apiKey = process.env.GEMINI_API_KEY;
|
| 89 |
-
|
| 90 |
-
if (!apiKey) {
|
| 91 |
-
console.error("FATAL: GEMINI_API_KEY secret is not configured in Hugging Face Space.");
|
| 92 |
-
return res.status(500).json({ error: 'GEMINI_API_KEY missing from environment secrets.' });
|
| 93 |
-
}
|
| 94 |
-
|
| 95 |
-
const { contents } = req.body;
|
| 96 |
-
|
| 97 |
-
// User requested specifically gemini-2.5-flash in the URL
|
| 98 |
-
const targetUrl = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent';
|
| 99 |
-
const proxyUrl = `https://corsproxy.io/?url=${encodeURIComponent(targetUrl)}`;
|
| 100 |
-
|
| 101 |
-
const response = await fetch(proxyUrl, {
|
| 102 |
-
method: 'POST',
|
| 103 |
-
headers: {
|
| 104 |
-
'Content-Type': 'application/json',
|
| 105 |
-
'x-goog-api-key': apiKey
|
| 106 |
-
},
|
| 107 |
-
body: JSON.stringify({
|
| 108 |
-
contents: contents
|
| 109 |
-
})
|
| 110 |
-
});
|
| 111 |
-
|
| 112 |
-
const data = await response.json();
|
| 113 |
-
|
| 114 |
-
if (data.error) {
|
| 115 |
-
console.error("Gemini API returned error:", data.error);
|
| 116 |
-
return res.status(response.status || 500).json({ error: data.error.message || 'Upstream Error' });
|
| 117 |
-
}
|
| 118 |
-
|
| 119 |
-
// Standardize text response for frontend consumption
|
| 120 |
-
const text = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
| 121 |
-
res.json({ text, candidates: data.candidates });
|
| 122 |
-
} catch (error) {
|
| 123 |
-
console.error("Server proxy error:", error);
|
| 124 |
-
res.status(500).json({ error: error.message });
|
| 125 |
-
}
|
| 126 |
-
});
|
| 127 |
-
|
| 128 |
-
// Citi Proxy
|
| 129 |
-
app.get('/api/accounts/account-transactions/partner/v1/accounts/details', (req, res) => res.json(CITI_ACCOUNTS));
|
| 130 |
-
|
| 131 |
-
// Serve Frontend
|
| 132 |
-
const __dist = path.join(__dirname, 'dist');
|
| 133 |
-
app.use(express.static(__dist));
|
| 134 |
-
|
| 135 |
-
// SPA Fallback
|
| 136 |
-
app.use((req, res) => {
|
| 137 |
-
if (req.path.startsWith('/api')) return res.status(404).json({ error: 'Endpoint missing' });
|
| 138 |
-
res.sendFile(path.join(__dist, 'index.html'));
|
| 139 |
-
});
|
| 140 |
-
|
| 141 |
-
app.listen(port, '0.0.0.0', () => console.log(`[Lumina Proxy] Node Online on Port ${port}`));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|