const express = require('express'); const { paginate, parsePaginationParams } = require('../pagination'); module.exports = function(ctx) { const router = express.Router(); // ===== UPDATE MANAGEMENT ENDPOINTS ===== // Check for updates router.post('/updates/check', ctx.asyncHandler(async (req, res) => { await ctx.updateManager.checkForUpdates(); const updates = ctx.updateManager.getAvailableUpdates(); res.json({ success: true, updates, count: updates.length }); }, 'updates-check')); // Get available updates router.get('/updates/available', ctx.asyncHandler(async (req, res) => { const updates = ctx.updateManager.getAvailableUpdates(); const paginationParams = parsePaginationParams(req.query); const result = paginate(updates, paginationParams); res.json({ success: true, updates: result.data, count: updates.length, ...(result.pagination && { pagination: result.pagination }) }); }, 'updates-available')); // Update a container router.post('/updates/update/:containerId', ctx.asyncHandler(async (req, res) => { const result = await ctx.updateManager.updateContainer(req.params.containerId, req.body); res.json({ success: true, result }); }, 'updates-update')); // Rollback update router.post('/updates/rollback/:containerId', ctx.asyncHandler(async (req, res) => { await ctx.updateManager.rollbackUpdate(req.params.containerId); res.json({ success: true, message: 'Rollback completed' }); }, 'updates-rollback')); // Get update history router.get('/updates/history', ctx.asyncHandler(async (req, res) => { const paginationParams = parsePaginationParams(req.query); // When paginating, fetch all history so pagination can slice correctly const fetchLimit = paginationParams ? Number.MAX_SAFE_INTEGER : (parseInt(req.query.limit) || 50); const history = ctx.updateManager.getHistory(fetchLimit); const result = paginate(history, paginationParams); res.json({ success: true, history: result.data, ...(result.pagination && { pagination: result.pagination }) }); }, 'updates-history')); // Configure auto-update router.post('/updates/auto-update/:containerId', ctx.asyncHandler(async (req, res) => { ctx.updateManager.configureAutoUpdate(req.params.containerId, req.body); res.json({ success: true, message: 'Auto-update configured' }); }, 'updates-auto-update')); // Schedule update router.post('/updates/schedule/:containerId', ctx.asyncHandler(async (req, res) => { const { scheduledTime } = req.body; if (!scheduledTime) { return ctx.errorResponse(res, 400, 'scheduledTime is required'); } ctx.updateManager.scheduleUpdate(req.params.containerId, scheduledTime); res.json({ success: true, message: 'Update scheduled', scheduledTime }); }, 'updates-schedule')); // ===== DASHCADDY SELF-UPDATE ENDPOINTS ===== // Get current version router.get('/system/version', ctx.asyncHandler(async (req, res) => { const local = ctx.selfUpdater.getLocalVersion(); res.json({ success: true, name: 'DashCaddy', version: local.version, commit: local.commit }); }, 'system-version')); // Check for DashCaddy update router.get('/system/update-check', ctx.asyncHandler(async (req, res) => { const result = await ctx.selfUpdater.checkForUpdate(); res.json({ success: true, ...result }); }, 'system-update-check')); // Apply available update router.post('/system/update-apply', ctx.asyncHandler(async (req, res) => { const check = await ctx.selfUpdater.checkForUpdate(); if (!check.available) { return res.json({ success: true, message: 'Already up to date' }); } // Start async — container may restart ctx.selfUpdater.applyUpdate(check.remote).catch(err => { ctx.logError('self-update', err); }); res.json({ success: true, message: 'Update initiated', fromVersion: check.local.version, toVersion: check.remote.version, }); }, 'system-update-apply')); // Get update status router.get('/system/update-status', ctx.asyncHandler(async (req, res) => { res.json({ success: true, status: ctx.selfUpdater.getStatus(), lastCheck: ctx.selfUpdater.lastCheckTime, lastResult: ctx.selfUpdater.lastCheckResult, }); }, 'system-update-status')); // Get self-update history router.get('/system/update-history', ctx.asyncHandler(async (req, res) => { const history = ctx.selfUpdater.getUpdateHistory(); res.json({ success: true, history }); }, 'system-update-history')); // List rollback versions router.get('/system/rollback-versions', ctx.asyncHandler(async (req, res) => { const versions = ctx.selfUpdater.getAvailableRollbacks(); res.json({ success: true, versions }); }, 'system-rollback-versions')); // Rollback to a previous version router.post('/system/rollback', ctx.asyncHandler(async (req, res) => { const { version } = req.body; if (!version) return ctx.errorResponse(res, 400, 'version is required'); ctx.selfUpdater.rollbackToVersion(version).catch(err => { ctx.logError('self-rollback', err); }); res.json({ success: true, message: `Rollback to ${version} initiated` }); }, 'system-rollback')); return router; };