Skip to content

chore(providers): improve provider structure and add notifications#452

Merged
JeanMeijer merged 1 commit intomainfrom
chore/improve-provider-structure-and-google-notifications
Mar 25, 2026
Merged

chore(providers): improve provider structure and add notifications#452
JeanMeijer merged 1 commit intomainfrom
chore/improve-provider-structure-and-google-notifications

Conversation

@JeanMeijer
Copy link
Copy Markdown
Collaborator

@JeanMeijer JeanMeijer commented Mar 25, 2026

Description

Briefly describe what you did and why.

Screenshots / Recordings

Add screenshots or recordings here to help reviewers understand your changes.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • UI/UX update
  • Docs update
  • Refactor / Cleanup

Related Areas

  • Authentication
  • Calendar UI
  • Data/API
  • Docs

Testing

  • Manual testing performed
  • Cross-browser testing (if UI changes)
  • Mobile responsiveness verified (if UI changes)

Checklist

  • I’ve read the CONTRIBUTING guide
  • My code works and is understandable and follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in complex areas
  • I have updated the documentation
  • Any dependent changes are merged and published

Notes

(Optional) Add anything else you'd like to share.

By submitting, I confirm I understand and stand behind this code. If AI was used, I’ve reviewed and verified everything myself.


Summary by cubic

Refactored calendar and task providers into clear sub-APIs and added Google Calendar webhook notifications. This simplifies integrations and makes provider methods consistent across Google and Microsoft.

  • New Features

    • Google Calendar notifications: subscribe/unsubscribe to event changes with channel id, resource id, token, and expiry via notifications.subscribe and notifications.unsubscribe.
    • Unified free/busy API: freeBusy.query({ schedules, timeMin, timeMax }) for Google and Microsoft.
  • Migration

    • Calendars: calendars()calendars.list(), calendar(id)calendars.get({ calendarId: id }), createCalendar(data)calendars.create({ calendar: data }), updateCalendar(id, data)calendars.update({ calendarId: id, calendar: data }), deleteCalendar(id)calendars.delete({ calendarId: id }).
    • Events: events(calendar, timeMin, timeMax, tz)events.list({ calendar, timeMin, timeMax, timeZone: tz }); sync(...)events.sync({...}); event(calendar, id, tz)events.get({ calendar, eventId: id, timeZone: tz }); createEvent(calendar, input)events.create({ calendar, event: input }); updateEvent(calendar, id, input)events.update({ calendar, eventId: id, event: input }); deleteEvent(calendarId, id, send)events.delete({ calendarId, eventId: id, sendUpdate: send }); moveEvent(src, dst, id, send)events.move({ sourceCalendar: src, destinationCalendar: dst, eventId: id, sendUpdate: send }); responseToEvent(calendarId, id, response)events.respond({ calendarId, eventId: id, response }).
    • Conferencing: createConference(agenda, start, end, tz?, calendarId?, eventId?)createConference({ agenda, startTime: start, endTime: end, timeZone: tz, calendarId, eventId }).
    • Tasks: tasks()tasks.list(), taskCollections()collections.list(), tasksForTaskCollection(id)collections.tasks({ taskCollectionId: id }), createTask(task)tasks.create({ task }), updateTask(task)tasks.update({ task }), deleteTask(listId, taskId)tasks.delete({ taskCollectionId: listId, taskId }).

Written for commit 1607bf2. Summary will update on new commits.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
analog Ready Ready Preview, Comment Mar 25, 2026 0:24am

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 30 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/providers/src/calendars/microsoft-calendar/events/index.ts">

<violation number="1" location="packages/providers/src/calendars/microsoft-calendar/events/index.ts:135">
P1: `move` returns a synthetic event with destination calendar metadata but never persists a move, causing state to diverge from Microsoft Calendar.</violation>
</file>

<file name="packages/providers/src/calendars/google-calendar/events/index.ts">

<violation number="1" location="packages/providers/src/calendars/google-calendar/events/index.ts:225">
P2: Calling `this.update()` here causes double error-wrapping and double logging. Both `create`'s and `update`'s `withErrorHandler` will catch, `console.error`, and wrap the same failure in nested `ProviderError` instances. Consider calling the client directly (as `update` does internally) or stripping the inner handler to avoid losing the original error in a `ProviderError` → `ProviderError` chain.</violation>
</file>

<file name="packages/providers/src/calendars/microsoft-calendar/utils.ts">

<violation number="1" location="packages/providers/src/calendars/microsoft-calendar/utils.ts:71">
P1: `dateTime` is serialized with a UTC `Z` offset for `ZonedDateTime`, which can cause Microsoft Graph to ignore the provided `timeZone` and store shifted times.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

syncToken = response["@odata.deltaLink"];
} while (pageToken);

return {
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: move returns a synthetic event with destination calendar metadata but never persists a move, causing state to diverge from Microsoft Calendar.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/providers/src/calendars/microsoft-calendar/events/index.ts, line 135:

<comment>`move` returns a synthetic event with destination calendar metadata but never persists a move, causing state to diverge from Microsoft Calendar.</comment>

<file context>
@@ -0,0 +1,273 @@
+        syncToken = response["@odata.deltaLink"];
+      } while (pageToken);
+
+      return {
+        changes,
+        syncToken,
</file context>
Fix with Cubic

}

return {
dateTime: value.toInstant().toString(),
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: dateTime is serialized with a UTC Z offset for ZonedDateTime, which can cause Microsoft Graph to ignore the provided timeZone and store shifted times.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/providers/src/calendars/microsoft-calendar/utils.ts, line 71:

<comment>`dateTime` is serialized with a UTC `Z` offset for `ZonedDateTime`, which can cause Microsoft Graph to ignore the provided `timeZone` and store shifted times.</comment>

<file context>
@@ -28,3 +28,50 @@ export function parseDateTime(dateTime: string, timeZone: string) {
+  }
+
+  return {
+    dateTime: value.toInstant().toString(),
+    timeZone:
+      originalTimeZone?.parsed === value.timeZoneId
</file context>
Suggested change
dateTime: value.toInstant().toString(),
dateTime: value.toPlainDateTime().toString(),
Fix with Cubic

} catch (error) {
// If the event already exists, update it instead of throwing an error
if (error instanceof ConflictError) {
return await this.update({
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Calling this.update() here causes double error-wrapping and double logging. Both create's and update's withErrorHandler will catch, console.error, and wrap the same failure in nested ProviderError instances. Consider calling the client directly (as update does internally) or stripping the inner handler to avoid losing the original error in a ProviderErrorProviderError chain.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/providers/src/calendars/google-calendar/events/index.ts, line 225:

<comment>Calling `this.update()` here causes double error-wrapping and double logging. Both `create`'s and `update`'s `withErrorHandler` will catch, `console.error`, and wrap the same failure in nested `ProviderError` instances. Consider calling the client directly (as `update` does internally) or stripping the inner handler to avoid losing the original error in a `ProviderError` → `ProviderError` chain.</comment>

<file context>
@@ -0,0 +1,446 @@
+      } catch (error) {
+        // If the event already exists, update it instead of throwing an error
+        if (error instanceof ConflictError) {
+          return await this.update({
+            calendar,
+            eventId: event.id,
</file context>
Fix with Cubic

@JeanMeijer JeanMeijer merged commit 6cca58e into main Mar 25, 2026
7 checks passed
@JeanMeijer JeanMeijer deleted the chore/improve-provider-structure-and-google-notifications branch March 25, 2026 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant