I want to fetch the CalDAV calendar and address book from the server, store the values locally on disk to cache them, and save the syncToken. Then, later, either in an interval or at the latest during the next start of the app, run the sync again. During that second sync, I want to get only those (and exactly those) calendar entries and contacts that were changed (which includes added, removed, or modified).
I cannot figure out how to do that, from the calendar and address book sync API of lambdabaa/dav = npm dav. The documentation does not describe that. There is a syncCalendar()
function, which from the name should do what I need, but the params and the overall process are not described. In the code, there is a syncToken
(and then there's also a ctag
and etag
). I am trying to use the syncToken, which should do what I need, but it doesn't.
After the sync, I get calendar.syncToken
and store it, and before the next sync (which might be after a restart), I restore the syncToken. But I get a full sync every time. It seems that I am using the API wrong, but I don't know what is right.
Dedicated test case:
git clone https://github.com/benbucksch/test-dav-sync/
yarn install
yarn start
The code, for self-contained-ness:
import dav from 'dav';
import config from './config.js'; /* Pseudo JSON File with:
export default
{
"serverURL": "https://...hostname.../remote.php/dav",
"username": "...",
"password": "..."
}
*/
var gJSONSavedFile = {}; // would normally be a file or database table
async function start() {
let syncToken = gJSONSavedFile.syncToken; // get it from file
console.info("sync token from file", syncToken);
console.time("calendar-connect");
let xhr = new dav.transport.Basic(
new dav.Credentials({
username: config.username,
password: config.password,
})
);
let account = await dav.createAccount({
server: config.serverURL,
//loadCollections: false,
//loadObjects: false,
xhr: xhr,
});
console.timeEnd("calendar-connect");
let calendar = account.calendars[0]; // just the first, just for testing
console.time("calendar sync");
console.log("sync token after init", calendar.syncToken);
if (syncToken) {
console.log("but setting sync token to", syncToken);
calendar.syncToken = syncToken; // TODO Already set. Doesn't work.
}
calendar = await dav.syncCalendar(calendar, {
syncToken: syncToken, // TODO Doesn't work
xhr: xhr,
});
console.timeEnd("calendar sync");
gJSONSavedFile.syncToken = calendar.syncToken; // save it
console.log("sync token after sync", gJSONSavedFile.syncToken);
console.log("Got", calendar.objects.length, "calendar entries");
}
(async () => {
try {
console.log("Test first start");
await start();
console.log("\nTest second start");
await start();
} catch (ex) {
console.error(ex);
}
})();
The output, when running against NextCloud:
Test first start
sync token from file undefined
calendar-connect: 4.765s
sync token after init http://sabre.io/ns/sync/1157
calendar sync: 2.562s
sync token after sync http://sabre.io/ns/sync/1157
Got 1051 calendar entries
Test second start
sync token from file http://sabre.io/ns/sync/1157
calendar-connect: 3.351s
sync token after init http://sabre.io/ns/sync/1157
but setting sync token to http://sabre.io/ns/sync/1157
calendar sync: 2.510s
sync token after sync http://sabre.io/ns/sync/1157
Got 1051 calendar entries
Done in 13.29s.
Expected output would be:
- Second sync returns 0 entries.
calendar.syncToken
is not set immediately after init and login.
The fact that the syncToken
is already set after init suggests that I am misunderstanding the API here.