| const express = require('express'); | |
| const cors = require('cors'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const { LRUCache } = require('lru-cache'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| const dbDirectory = path.join(__dirname, 'database'); | |
| if (!fs.existsSync(dbDirectory)) { | |
| fs.mkdirSync(dbDirectory); | |
| } | |
| const cache = new LRUCache({ | |
| max: 500, | |
| ttl: 1000 * 60 * 60 * 24 * 30, | |
| allowStale: false, | |
| updateAgeOnGet: true, | |
| updateAgeOnHas: true, | |
| }); | |
| function loadDatabasesIntoCache() { | |
| const ownerDirs = fs.readdirSync(dbDirectory); | |
| for (const owner of ownerDirs) { | |
| const ownerPath = path.join(dbDirectory, owner); | |
| if (fs.statSync(ownerPath).isDirectory()) { | |
| const files = fs.readdirSync(ownerPath); | |
| for (const file of files) { | |
| if (path.extname(file) === '.json') { | |
| const dbName = path.basename(file, '.json'); | |
| const filePath = path.join(ownerPath, file); | |
| const cacheKey = `${owner}_${dbName}`; | |
| try { | |
| const data = fs.readFileSync(filePath, 'utf8'); | |
| cache.set(cacheKey, JSON.parse(data)); | |
| } catch (e) { | |
| console.error(`Gagal memuat ${file} untuk owner ${owner} ke cache.`, e); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| console.log('Semua database dari disk telah dimuat ke LRU Cache.'); | |
| } | |
| app.use(cors()); | |
| app.use(express.json({ limit: '50mb' })); | |
| app.get('/db/:owner/:name', (req, res) => { | |
| const { owner, name } = req.params; | |
| const cacheKey = `${owner}_${name}`; | |
| const data = cache.get(cacheKey); | |
| if (data) { | |
| return res.status(200).json(data); | |
| } | |
| const filePath = path.join(dbDirectory, owner, `${name}.json`); | |
| if (fs.existsSync(filePath)) { | |
| try { | |
| const fileData = JSON.parse(fs.readFileSync(filePath, 'utf8')); | |
| cache.set(cacheKey, fileData); | |
| return res.status(200).json(fileData); | |
| } catch (e) { | |
| return res.status(500).json({ success: false, message: 'Gagal membaca database.' }); | |
| } | |
| } else { | |
| return res.status(200).json({}); | |
| } | |
| }); | |
| app.post('/db/:owner/:name', (req, res) => { | |
| try { | |
| const { owner, name } = req.params; | |
| const data = req.body; | |
| const cacheKey = `${owner}_${name}`; | |
| cache.set(cacheKey, data); | |
| const ownerDir = path.join(dbDirectory, owner); | |
| if (!fs.existsSync(ownerDir)) { | |
| fs.mkdirSync(ownerDir, { recursive: true }); | |
| } | |
| const filePath = path.join(ownerDir, `${name}.json`); | |
| fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); | |
| res.status(200).json({ success: true, message: 'Database berhasil disimpan.' }); | |
| } catch (error) { | |
| res.status(500).json({ success: false, message: 'Terjadi kesalahan internal.' }); | |
| } | |
| }); | |
| app.listen(PORT, () => { | |
| loadDatabasesIntoCache(); | |
| console.log(`Server database multi-tenant berjalan di port ${PORT}.`); | |
| }); |