229 lines
6.3 KiB
JavaScript
229 lines
6.3 KiB
JavaScript
/**
|
|
* Express server to serve FFXI Trust character data from PostgreSQL database
|
|
*/
|
|
|
|
const express = require('express');
|
|
const { Pool } = require('pg');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Database configuration
|
|
let dbConfig = {};
|
|
|
|
// Try to read from environment variables first
|
|
if (process.env.PSQL_HOST && process.env.PSQL_USER && process.env.PSQL_DBNAME) {
|
|
console.log('Using database configuration from environment variables');
|
|
dbConfig = {
|
|
PSQL_USER: process.env.PSQL_USER,
|
|
PSQL_HOST: process.env.PSQL_HOST,
|
|
PSQL_DBNAME: process.env.PSQL_DBNAME,
|
|
PSQL_PASSWORD: process.env.PSQL_PASSWORD,
|
|
PSQL_PORT: process.env.PSQL_PORT || '5432',
|
|
};
|
|
} else {
|
|
// Fall back to db.conf file
|
|
try {
|
|
console.log('Reading database configuration from db.conf file');
|
|
const dbConfFile = fs.readFileSync('db.conf', 'utf8');
|
|
|
|
// Parse the db.conf file
|
|
dbConfFile.split('\n').forEach(line => {
|
|
if (line.trim() === '') return;
|
|
|
|
const [key, value] = line.split('=');
|
|
if (key && value) {
|
|
// Remove quotes if present
|
|
const cleanValue = value.replace(/^['"]|['"]$/g, '');
|
|
dbConfig[key] = cleanValue;
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.error('Error reading db.conf file:', err.message);
|
|
console.error('Please ensure db.conf exists or provide environment variables');
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Configure PostgreSQL connection
|
|
const pool = new Pool({
|
|
user: dbConfig.PSQL_USER,
|
|
host: dbConfig.PSQL_HOST,
|
|
database: dbConfig.PSQL_DBNAME,
|
|
password: dbConfig.PSQL_PASSWORD,
|
|
port: dbConfig.PSQL_PORT,
|
|
});
|
|
|
|
// Create Express app
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
// Middleware to parse JSON bodies
|
|
app.use(express.json());
|
|
|
|
// Set up EJS as the template engine
|
|
app.set('view engine', 'ejs');
|
|
app.set('views', path.join(__dirname, '.'));
|
|
|
|
// Serve static files (except index.html which will be rendered with EJS)
|
|
app.use(express.static('.', {
|
|
index: false
|
|
}));
|
|
|
|
// Render index.ejs with environment variables
|
|
app.get('/', (req, res) => {
|
|
res.render('index.ejs', {
|
|
process: {
|
|
env: {
|
|
PSQL_HOST: dbConfig.PSQL_HOST,
|
|
PSQL_PORT: dbConfig.PSQL_PORT,
|
|
PSQL_USER: dbConfig.PSQL_USER,
|
|
PSQL_PASSWORD: dbConfig.PSQL_PASSWORD,
|
|
PSQL_DBNAME: dbConfig.PSQL_DBNAME
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// API endpoint to get all trusts
|
|
app.get('/api/trusts', async (req, res) => {
|
|
try {
|
|
const client = await pool.connect();
|
|
const result = await client.query('SELECT * FROM trusts ORDER BY name');
|
|
const trusts = result.rows;
|
|
client.release();
|
|
|
|
res.json(trusts);
|
|
} catch (err) {
|
|
console.error('Error executing query', err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// API endpoint to get a specific trust by ID
|
|
app.get('/api/trusts/:id', async (req, res) => {
|
|
try {
|
|
const id = parseInt(req.params.id);
|
|
const client = await pool.connect();
|
|
const result = await client.query('SELECT * FROM trusts WHERE id = $1', [id]);
|
|
|
|
if (result.rows.length === 0) {
|
|
res.status(404).json({ error: 'Trust not found' });
|
|
} else {
|
|
res.json(result.rows[0]);
|
|
}
|
|
|
|
client.release();
|
|
} catch (err) {
|
|
console.error('Error executing query', err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// API endpoint to get trusts by role
|
|
app.get('/api/trusts/role/:role', async (req, res) => {
|
|
try {
|
|
const role = req.params.role;
|
|
const client = await pool.connect();
|
|
const result = await client.query('SELECT * FROM trusts WHERE role = $1 ORDER BY name', [role]);
|
|
const trusts = result.rows;
|
|
client.release();
|
|
|
|
res.json(trusts);
|
|
} catch (err) {
|
|
console.error('Error executing query', err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// API endpoint to search trusts
|
|
app.get('/api/trusts/search/:query', async (req, res) => {
|
|
try {
|
|
const query = req.params.query;
|
|
const client = await pool.connect();
|
|
const result = await client.query(`
|
|
SELECT * FROM trusts
|
|
WHERE
|
|
name ILIKE $1 OR
|
|
role ILIKE $1 OR
|
|
job ILIKE $1 OR
|
|
spells ILIKE $1 OR
|
|
abilities ILIKE $1
|
|
ORDER BY name
|
|
`, [`%${query}%`]);
|
|
|
|
const trusts = result.rows;
|
|
client.release();
|
|
|
|
res.json(trusts);
|
|
} catch (err) {
|
|
console.error('Error executing query', err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// API endpoint to toggle the acquired status of a trust
|
|
app.put('/api/trusts/:id/toggle-acquired', async (req, res) => {
|
|
try {
|
|
const id = parseInt(req.params.id);
|
|
const client = await pool.connect();
|
|
|
|
// Get the current acquired status
|
|
const getResult = await client.query('SELECT acquired FROM trusts WHERE id = $1', [id]);
|
|
|
|
if (getResult.rows.length === 0) {
|
|
client.release();
|
|
return res.status(404).json({ error: 'Trust not found' });
|
|
}
|
|
|
|
// Toggle the acquired status
|
|
const currentStatus = getResult.rows[0].acquired;
|
|
const newStatus = !currentStatus;
|
|
|
|
// Update the acquired status
|
|
await client.query('UPDATE trusts SET acquired = $1 WHERE id = $2', [newStatus, id]);
|
|
|
|
// Get the updated trust
|
|
const result = await client.query('SELECT * FROM trusts WHERE id = $1', [id]);
|
|
client.release();
|
|
|
|
res.json(result.rows[0]);
|
|
} catch (err) {
|
|
console.error('Error executing query', err);
|
|
res.status(500).json({ error: 'Database error' });
|
|
}
|
|
});
|
|
|
|
// Health check endpoint
|
|
app.get('/health', async (req, res) => {
|
|
try {
|
|
// Check database connection
|
|
const client = await pool.connect();
|
|
await client.query('SELECT 1');
|
|
client.release();
|
|
|
|
res.status(200).json({
|
|
status: 'ok',
|
|
message: 'Service is healthy',
|
|
timestamp: new Date().toISOString(),
|
|
version: process.env.npm_package_version || '1.0.0',
|
|
database: 'connected'
|
|
});
|
|
} catch (err) {
|
|
console.error('Health check failed:', err);
|
|
res.status(500).json({
|
|
status: 'error',
|
|
message: 'Service is unhealthy',
|
|
timestamp: new Date().toISOString(),
|
|
error: err.message,
|
|
database: 'disconnected'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Start the server
|
|
app.listen(PORT, () => {
|
|
console.log(`Server running on port ${PORT}`);
|
|
console.log(`Access the web app at http://localhost:${PORT}`);
|
|
console.log(`API available at http://localhost:${PORT}/api/trusts`);
|
|
});
|