import cors from 'cors'; import dotenv from 'dotenv'; import express from 'express'; import { Client, Databases, Query } from 'node-appwrite'; dotenv.config(); const app = express(); app.use(cors()); app.use(express.json()); const requiredEnv = ['APPWRITE_ENDPOINT', 'APPWRITE_PROJECT_ID', 'APPWRITE_API_KEY']; const missingEnv = requiredEnv.filter((key) => !process.env[key]); const databaseId = process.env.APPWRITE_DATABASE_ID || process.env.VITE_APPWRITE_DATABASE_ID || ''; const collectionIds = { servers: process.env.APPWRITE_COLLECTION_SERVERS_ID || process.env.VITE_APPWRITE_COLLECTION_SERVERS_ID || '', githubRepos: process.env.APPWRITE_COLLECTION_GITHUB_REPOS_ID || process.env.VITE_APPWRITE_COLLECTION_GITHUB_REPOS_ID || '', auditLogs: process.env.APPWRITE_COLLECTION_AUDIT_LOGS_ID || process.env.VITE_APPWRITE_COLLECTION_AUDIT_LOGS_ID || '', cloudAccounts: process.env.APPWRITE_COLLECTION_CLOUDFLARE_ACCOUNTS_ID || process.env.VITE_APPWRITE_COLLECTION_CLOUDFLARE_ACCOUNTS_ID || '', }; const client = new Client() .setEndpoint(process.env.APPWRITE_ENDPOINT || '') .setProject(process.env.APPWRITE_PROJECT_ID || '') .setKey(process.env.APPWRITE_API_KEY || ''); const databases = new Databases(client); const getPaginationQueries = (request) => { const limit = Number.parseInt(request.query.limit ?? '25', 10); const offset = Number.parseInt(request.query.offset ?? '0', 10); const queries = []; if (!Number.isNaN(limit)) { queries.push(Query.limit(Math.min(Math.max(limit, 1), 100))); } if (!Number.isNaN(offset)) { queries.push(Query.offset(Math.max(offset, 0))); } return queries; }; const listCollection = (collectionId, extraQueries = []) => async (request, response) => { if (missingEnv.length > 0) { return response.status(500).json({ error: 'Missing required environment variables.', missing: missingEnv, }); } if (!databaseId || !collectionId) { return response.status(500).json({ error: 'Missing Appwrite database or collection configuration.', databaseId, collectionId, }); } try { const documents = await databases.listDocuments( databaseId, collectionId, [...getPaginationQueries(request), ...extraQueries] ); return response.json(documents); } catch (error) { return response.status(500).json({ error: 'Failed to fetch Appwrite documents.', details: error.message, }); } }; app.get('/health', (request, response) => { response.json({ status: 'ok' }); }); app.get('/servers', listCollection(collectionIds.servers)); app.get('/github-repos', listCollection(collectionIds.githubRepos)); app.get('/cloud-accounts', listCollection(collectionIds.cloudAccounts)); app.get('/audit-logs', listCollection(collectionIds.auditLogs, [Query.orderDesc('timestamp')])); const port = Number.parseInt(process.env.BACKEND_PORT ?? '4000', 10); app.listen(port, () => { // eslint-disable-next-line no-console console.log(`Backend listening on http://localhost:${port}`); });