feat(cardav): implement POST /accounts/:id/sync endpoint

Adds route to sync all enabled addressbooks for an account with mock support for tests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Ulas Kalayci
2026-05-04 17:54:03 +02:00
parent f895776911
commit 674fe796b3
4 changed files with 145 additions and 6 deletions
+22
View File
@@ -180,4 +180,26 @@ router.put('/addressbooks/:id', async (req, res) => {
}
});
/**
* POST /api/v1/contacts/cardav/accounts/:id/sync
* Sync all enabled addressbooks for account.
* Response: { data: { synced: boolean, contactsAdded: number, contactsUpdated: number } }
*/
router.post('/accounts/:id/sync', async (req, res) => {
try {
const id = parseInt(req.params.id, 10);
if (!id || id < 1) return res.status(400).json({ error: 'Invalid ID', code: 400 });
const account = db.get().prepare('SELECT * FROM carddav_accounts WHERE id = ?').get(id);
if (!account) return res.status(404).json({ error: 'Account nicht gefunden', code: 404 });
const result = await CardDAVSync.syncAccount(id);
res.json({ data: result });
} catch (err) {
log.error('Error syncing account:', err);
res.status(500).json({ error: 'Interner Fehler', code: 500 });
}
});
export default router;
+15
View File
@@ -467,6 +467,11 @@ function toggleAddressbook(addressbookId, enabled) {
* @returns {Promise<Object>} { synced, errors }
*/
async function syncAccount(accountId) {
// Use mock if set (for testing)
if (_syncAccountMock) {
return _syncAccountMock(accountId);
}
try {
const account = db.get().prepare('SELECT * FROM carddav_accounts WHERE id = ?').get(accountId);
if (!account) {
@@ -884,6 +889,7 @@ export {
// Helpers (exported for testing)
parseVCard,
_mockTestConnection,
_mockSyncAccount,
};
// --------------------------------------------------------
@@ -891,6 +897,7 @@ export {
// --------------------------------------------------------
let _testConnectionMock = null;
let _syncAccountMock = null;
/**
* ONLY FOR TESTING: Mock testConnection for unit tests
@@ -899,3 +906,11 @@ let _testConnectionMock = null;
function _mockTestConnection(mockFn) {
_testConnectionMock = mockFn;
}
/**
* ONLY FOR TESTING: Mock syncAccount for unit tests
* @param {Function|null} mockFn - Mock function or null to reset
*/
function _mockSyncAccount(mockFn) {
_syncAccountMock = mockFn;
}