| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- const express = require('express');
- const fs = require('fs');
- const path = require('path');
- const {parser} = require('stream-json');
- const {streamObject} = require('stream-json/streamers/StreamObject');
- const app = express();
- const PORT = 8080;
- const SNAPSHOT_DIR = path.join(__dirname, 'snapshots');
- // Ensure snapshot folder exists
- if(!fs.existsSync(SNAPSHOT_DIR)) {
- fs.mkdirSync(SNAPSHOT_DIR);
- }
- // app.use(bodyParser.json({limit: '100mb'})); // Accept large JSON payloads
- app.use(express.static(path.join(__dirname, 'public')));
- app.use(express.text({type: 'text/plain', limit: '100mb'}));
- // List all snapshots
- app.get('/api/snapshots', async(req, res) => {
- const jsonFiles = fs.readdirSync(SNAPSHOT_DIR)
- .filter(f => f.endsWith('.json'));
- const meta = await Promise.all(jsonFiles.map(async f => ({
- name: f,
- comment: await getComment(f),
- timestamp: fs.statSync(path.join(SNAPSHOT_DIR, f)).mtimeMs
- })));
- const sorted = meta
- .sort((a, b) => b.timestamp - a.timestamp);
- res.json(sorted);
- });
- // Save a new snapshot
- app.post('/api/snapshots', (req, res) => {
- const data = req.body;
- const filename = `snapshot-${getFormattedDate()}.json`;
- const filepath = path.join(SNAPSHOT_DIR, filename);
- fs.writeFile(filepath, data, (err) => {
- if(err) {
- res.status = 500;
- res.json({message: 'something went wrong'});
- } else {
- res.json({success: true, filename});
- }
- });
- });
- // Load a snapshot by filename
- app.get('/api/snapshots/:filename', (req, res) => {
- const {filename} = req.params;
- const filepath = path.join(SNAPSHOT_DIR, filename);
- if(!fs.existsSync(filepath)) {
- return res.status(404).json({error: 'Snapshot not found'});
- }
- const data = fs.readFileSync(filepath, 'utf-8');
- res.json(JSON.parse(data));
- });
- // Delete a snapshot by filename
- app.delete('/api/snapshots/:filename', (req, res) => {
- const {filename} = req.params;
- const filepath = path.join(SNAPSHOT_DIR, filename);
- if(!fs.existsSync(filepath)) {
- return res.status(404).json({error: 'Snapshot not found'});
- }
- fs.unlinkSync(filepath);
- res.json({success: true});
- });
- // Start server with optional port argument
- const portArg = process.argv.find(arg => arg.startsWith('--port='));
- const portToUse = portArg ? parseInt(portArg.split('=')[1], 10) : PORT;
- app.listen(portToUse, () => {
- console.log(`🟢 Server running at http://localhost:${portToUse}`);
- });
- function getFormattedDate() {
- const d = new Date();
- const pad = n => String(n).padStart(2, '0');
- const date = [d.getFullYear(), pad(d.getMonth() + 1), pad(d.getDate())].join('-');
- const time = [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds())].join('-');
- return `${date}_${time}`;
- }
- const getComment = (f) => new Promise((_resolve) => {
- const timeout = setTimeout(() => {resolve('')}, 500); // Don't let it stall
- const resolve = (value) => {
- _resolve(value);
- clearTimeout(timeout);
- pipeline.destroy(); // Stop once we get the value
- };
- const pipeline = fs.createReadStream(path.join(SNAPSHOT_DIR, f))
- .pipe(parser())
- .pipe(streamObject())
- // Assuming comment is positioned first in the json
- pipeline.on('data', ({key, value}) => {
- if(key === 'comment') resolve(value);
- else resolve('');
- });
- pipeline.on('close', () => {
- resolve('');
- });
- pipeline.on('error', () => {
- resolve('')
- });
- });
|