123 Zeilen
3.0 KiB
TypeScript
123 Zeilen
3.0 KiB
TypeScript
import { Router } from 'express'
|
|
import { authenticate, authorize } from '../middleware/auth'
|
|
import { syncService } from '../services/syncService'
|
|
import { logger } from '../utils/logger'
|
|
import type { AuthRequest } from '../middleware/auth'
|
|
|
|
const router = Router()
|
|
|
|
// Receive sync data from another node
|
|
router.post('/receive', authenticate, async (req: AuthRequest, res, next) => {
|
|
try {
|
|
const nodeId = req.headers['x-node-id'] as string
|
|
if (!nodeId) {
|
|
return res.status(400).json({
|
|
error: { message: 'Missing node ID in headers' }
|
|
})
|
|
}
|
|
|
|
const result = await syncService.receiveSync(req.body)
|
|
|
|
res.json(result)
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
// Get sync status
|
|
router.get('/status', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
|
|
try {
|
|
const status = syncService.getSyncStatus()
|
|
|
|
res.json({
|
|
success: true,
|
|
data: status
|
|
})
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
// Trigger manual sync
|
|
router.post('/trigger', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
|
|
try {
|
|
// Run sync in background
|
|
syncService.triggerSync().catch(error => {
|
|
logger.error('Background sync failed:', error)
|
|
})
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Sync triggered successfully'
|
|
})
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
// Sync with specific node
|
|
router.post('/sync/:nodeId', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
|
|
try {
|
|
const { nodeId } = req.params
|
|
const result = await syncService.syncWithNode(nodeId)
|
|
|
|
res.json({
|
|
success: true,
|
|
data: result
|
|
})
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
// Get sync conflicts
|
|
router.get('/conflicts', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
|
|
try {
|
|
const { db } = await import('../config/database')
|
|
|
|
const conflicts = db.prepare(`
|
|
SELECT * FROM sync_conflicts
|
|
WHERE resolution_status = 'pending'
|
|
ORDER BY created_at DESC
|
|
`).all()
|
|
|
|
res.json({
|
|
success: true,
|
|
data: conflicts
|
|
})
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
// Resolve sync conflict
|
|
router.post('/conflicts/:conflictId/resolve', authenticate, authorize('admin'), async (req: AuthRequest, res, next) => {
|
|
try {
|
|
const { conflictId } = req.params
|
|
const { resolution, data } = req.body
|
|
const { db } = await import('../config/database')
|
|
|
|
// Update conflict status
|
|
db.prepare(`
|
|
UPDATE sync_conflicts
|
|
SET resolution_status = 'resolved',
|
|
resolved_by = ?,
|
|
resolved_at = ?
|
|
WHERE id = ?
|
|
`).run(req.user!.id, new Date().toISOString(), conflictId)
|
|
|
|
// Apply resolution if needed
|
|
if (resolution === 'apply' && data) {
|
|
await syncService.receiveSync(data)
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
message: 'Conflict resolved successfully'
|
|
})
|
|
} catch (error) {
|
|
next(error)
|
|
}
|
|
})
|
|
|
|
export default router |