feat: database backups & analytics site management

- Added manual database backup functionality with pg_dump
- Added cron-based automated backups to Google Drive and Dropbox
- Added ability to manually add, edit, and delete sites in Analytics
- Added 1-day timeframe filter in Analytics page
- Updated Dockerfile to include postgresql-client
This commit is contained in:
mstfyldz
2026-06-02 17:44:46 +03:00
parent e28fa966e3
commit e5dc347a0b
12 changed files with 686 additions and 10 deletions
+47
View File
@@ -0,0 +1,47 @@
import { NextResponse } from 'next/server'
import { readConfig } from '@/lib/config'
import { createPgDumpStream } from '@/lib/backup'
// GET /api/db/backup?dbId=...
export async function GET(req: Request) {
const { searchParams } = new URL(req.url)
const dbId = searchParams.get('dbId')
if (!dbId) return NextResponse.json({ error: 'Missing dbId' }, { status: 400 })
const config = await readConfig()
const db = config.databases.find(d => d.id === dbId)
if (!db) return NextResponse.json({ error: 'Database not found' }, { status: 404 })
try {
const child = await createPgDumpStream(db)
const dateStr = new Date().toISOString().replace(/[:.]/g, '-')
const filename = `${db.name}_${dateStr}.sql`
// Stream the output of pg_dump to the response
const stream = new ReadableStream({
start(controller) {
child.stdout.on('data', (chunk) => controller.enqueue(chunk))
child.on('close', (code) => {
if (code === 0) {
controller.close()
} else {
controller.error(new Error(`pg_dump exited with code ${code}`))
}
})
child.on('error', (err) => controller.error(err))
},
cancel() {
child.kill()
}
})
return new NextResponse(stream, {
headers: {
'Content-Type': 'application/sql',
'Content-Disposition': `attachment; filename="${filename}"`
}
})
} catch (e: any) {
return NextResponse.json({ error: e.message }, { status: 500 })
}
}