@timesheet/plugin-google-calendar 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/taskSync.js +23 -4
- package/manifest.json +1 -1
- package/package.json +1 -1
package/dist/lib/taskSync.js
CHANGED
|
@@ -194,6 +194,21 @@ async function syncCalendar(context, projectMapping) {
|
|
|
194
194
|
if (!syncToken && metadataSyncToken) {
|
|
195
195
|
syncToken = metadataSyncToken;
|
|
196
196
|
}
|
|
197
|
+
try {
|
|
198
|
+
return await fetchAndSyncEvents(context, client, projectMapping, calendarId, syncStateKey, syncToken);
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
// Google returns 400 or 410 when a sync token is invalid/expired — clear it and do a full resync
|
|
202
|
+
const errMsg = String(err);
|
|
203
|
+
if (syncToken && (errMsg.includes('(410)') || errMsg.includes('Invalid sync token'))) {
|
|
204
|
+
context.logger.warn('Sync token expired, performing full resync', { calendarId });
|
|
205
|
+
await context.state.delete(syncStateKey);
|
|
206
|
+
return await fetchAndSyncEvents(context, client, projectMapping, calendarId, syncStateKey, undefined);
|
|
207
|
+
}
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
async function fetchAndSyncEvents(context, client, projectMapping, calendarId, syncStateKey, syncToken) {
|
|
197
212
|
let pageToken;
|
|
198
213
|
let nextSyncToken;
|
|
199
214
|
let syncedCount = 0;
|
|
@@ -303,10 +318,10 @@ function toTaskDateRange(event) {
|
|
|
303
318
|
let endRaw = event.end?.dateTime;
|
|
304
319
|
// Handle all-day events (date field instead of dateTime)
|
|
305
320
|
if (!startRaw && event.start?.date) {
|
|
306
|
-
startRaw = `${event.start.date}T00:00:
|
|
321
|
+
startRaw = `${event.start.date}T00:00:00+00:00`;
|
|
307
322
|
}
|
|
308
323
|
if (!endRaw && event.end?.date) {
|
|
309
|
-
endRaw = `${event.end.date}T00:00:
|
|
324
|
+
endRaw = `${event.end.date}T00:00:00+00:00`;
|
|
310
325
|
}
|
|
311
326
|
if (!startRaw || !endRaw) {
|
|
312
327
|
return null;
|
|
@@ -317,8 +332,8 @@ function toTaskDateRange(event) {
|
|
|
317
332
|
return null;
|
|
318
333
|
}
|
|
319
334
|
return {
|
|
320
|
-
startDateTime: start
|
|
321
|
-
endDateTime: end
|
|
335
|
+
startDateTime: toTimesheetDateTime(start),
|
|
336
|
+
endDateTime: toTimesheetDateTime(end)
|
|
322
337
|
};
|
|
323
338
|
}
|
|
324
339
|
function buildGoogleEventPayload(task) {
|
|
@@ -478,6 +493,10 @@ async function ensureWatchChannels(context) {
|
|
|
478
493
|
}
|
|
479
494
|
}
|
|
480
495
|
}
|
|
496
|
+
/** Format a Date to the offset format the Timesheet backend expects: yyyy-MM-dd'T'HH:mm:ss+00:00 */
|
|
497
|
+
function toTimesheetDateTime(date) {
|
|
498
|
+
return date.toISOString().replace(/\.\d{3}Z$/, '+00:00');
|
|
499
|
+
}
|
|
481
500
|
function readMetadataString(metadata, key) {
|
|
482
501
|
const value = metadata[key];
|
|
483
502
|
if (typeof value === 'string' && value.trim().length > 0) {
|
package/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "google-calendar-sync",
|
|
3
3
|
"name": "Google Calendar Sync",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.2",
|
|
5
5
|
"description": "Synchronize Timesheet tasks with Google Calendar",
|
|
6
6
|
"longDescription": "Bidirectional synchronization between Timesheet tasks and Google Calendar events.",
|
|
7
7
|
"icon": "google-calendar",
|