Skip to content

♻️(caldav) remove tsdav library and refactor network path#58

Merged
sylvinus merged 3 commits into
mainfrom
remove-tsdav
May 30, 2026
Merged

♻️(caldav) remove tsdav library and refactor network path#58
sylvinus merged 3 commits into
mainfrom
remove-tsdav

Conversation

@sylvinus
Copy link
Copy Markdown
Member

@sylvinus sylvinus commented May 29, 2026

We were building too much workarounds around the core tsdav library, so we switch to a partial reimplementation for what actually matters for our more narrow usecase. Also cleanup various other deps and unify the network call path for all caldav requests

Summary by CodeRabbit

  • Bug Fixes

    • Prevented concurrent login redirects from overwriting stored return URLs.
  • Infrastructure

    • Improved frontend Docker build for non-root containers and npm cache handling.
  • Refactoring

    • Major calendar backend overhaul: unified DAV request layer, simplified types, and streamlined calendar/event flows.
  • Chores

    • Ignored local npm cache to avoid committing transient artifacts.

Review Change Stack

We were building too much workarounds around the core tsdav library,
so we switch to a partial reimplementation for what actually matters
for our more narrow usecase. Also cleanup various other deps and unify
the network call path for all caldav requests
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Warning

Review limit reached

@sylvinus, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 15 minutes and 11 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0cc24d66-733a-440d-8004-a76aa024a3f8

📥 Commits

Reviewing files that changed from the base of the PR and between 5dfb7b6 and a2daca1.

⛔ Files ignored due to path filters (1)
  • src/frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (6)
  • src/frontend/apps/calendars/package.json
  • src/frontend/apps/calendars/src/features/home/HomePage.tsx
  • src/frontend/apps/calendars/src/pages/index.tsx
  • src/frontend/apps/calendars/src/pages/integrations.tsx
  • src/frontend/apps/calendars/src/pages/resources.tsx
  • src/frontend/apps/calendars/src/pages/settings.tsx
📝 Walkthrough

Walkthrough

Refactors frontend CalDAV integration: replace tsdav helpers with a unified DavClient/davRequest layer (XML building/parsing, error handling), simplify CalDAV types, rewrite CalDavService to use davRequest for PROPFIND/REPORT/MKCALENDAR/PROPPATCH/PUT/DELETE/MOVE with explicit ETag handling, add tests, and update integration points and Docker/npm config.

Changes

CalDAV Client Refactoring

Layer / File(s) Summary
Docker, npm cache, and package deps
.gitignore, src/frontend/Dockerfile, src/frontend/apps/calendars/package.json
Adds .npm/ to gitignore, makes Docker pre-create/chown frontend home and set HOME/NPM_CONFIG_CACHE, and updates package.json devDeps (adds jsdom env).
DavClient unified request layer
src/frontend/apps/calendars/src/features/calendar/utils/DavClient.ts, src/frontend/apps/calendars/src/features/calendar/utils/__tests__/DavClient.test.ts
Adds davRequest with shared headers/credentials, PROPFIND body builder, safe XML parsing, parseMultistatus, SabreDAV error extraction, and tests validating PROPFIND/REPORT/GET/PUT/DELETE shapes and parsing.
CalDAV XML helpers and query builders
src/frontend/apps/calendars/src/features/calendar/services/dav/caldav-helpers.ts, src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/caldav-helpers.test.ts
Introduce NS constants, extend CalendarProps with timezone, add buildCalendarQueryXml, convert several helpers to internal-only, rebuild CALENDAR_PROPS, and add asResult wrapper; update XML builder tests.
Types simplification & helper removals
src/frontend/apps/calendars/src/features/calendar/services/dav/types/*, src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/*
Simplify CalDAV types (credentials/account/calendar/event/free-busy), remove many helper modules and type files (dav-helper, event-calendar-helper, ics-helper, timezone tests, types-helper, addressbook types, options types, VCardComponent), and remove barrel re-exports.
CalDavService refactor to use davRequest
src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts
Refactors service to call davRequest/asResult for connect, calendar/event CRUD, sharing/scheduling/free-busy; implements deterministic connect URL derivation and explicit ETag/If-Match/If-None-Match handling.
CalDavService & DavClient tests
src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/CalDavService.connect.test.ts, src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/CalDavService.moveEvent.test.ts, DavClient tests
Adds connect() regression tests for principal/home URL construction and encoding, updates moveEvent tests to assert MOVE request shape, and includes DavClient parsing/request tests.
Integration updates and small fixes
src/frontend/apps/calendars/src/features/calendar/contexts/CalendarContext.tsx, src/frontend/apps/calendars/src/features/resources/api/useResourcePrincipals.ts, src/frontend/apps/calendars/src/features/settings/api/useWorkingHours.ts, src/frontend/apps/calendars/src/features/api/fetchApi.ts, src/frontend/apps/calendars/src/styles/globals.scss
CalendarContext import/callsite updates, useResourcePrincipals → davRequest PROPFIND, useWorkingHours now uses useCalendarContext, redirectToLogin() made concurrency-safe, and .selection-area styles removed.

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main objective: removing the tsdav library and refactoring the network path for CalDAV. It accurately reflects the primary changes throughout the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts (1)

40-58: 🧹 Nitpick | 🔵 Trivial | 💤 Low value

Remove unused import parseSharePrivilege.

Static analysis indicates parseSharePrivilege is imported but never used in this file after the refactor.

🧹 Proposed fix
 import {
   buildProppatchXml,
   buildShareRequestXml,
   buildUnshareRequestXml,
   buildMkCalendarXml,
   buildCalendarQueryXml,
   escapeXml,
   CALENDAR_PROPS,
   NS,
   parseCalendarComponents,
-  parseSharePrivilege,
   parseInviteSharees,
   parseInviteOrganizerEmail,
   parseCalendarOrder,
   getCalendarUrlFromEventUrl,
   asResult,
   type ShareeXmlParams,
   type CalendarProps,
 } from './caldav-helpers'
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts`
around lines 40 - 58, Remove the unused import parseSharePrivilege from the
import list at the top of CalDavService.ts (the import that pulls from
'./caldav-helpers'); update the import statement that currently includes
parseSharePrivilege alongside buildProppatchXml, buildShareRequestXml, etc., to
no longer reference parseSharePrivilege and run the linter/TypeScript compile to
confirm no other references to parseSharePrivilege remain.
src/frontend/apps/calendars/src/features/api/fetchApi.ts (1)

32-38: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent permanent redirect lock if sessionStorage write fails.

On Line 33, redirectInFlight is set before sessionStorage.setItem (Line 34). If storage throws, the function exits and future 401s are no-ops, so users may never be redirected to login in that runtime.

Suggested fix
 export function redirectToLogin() {
   if (redirectInFlight) return;
-  redirectInFlight = true;
-  sessionStorage.setItem(
-    SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL,
-    window.location.href,
-  );
+  redirectInFlight = true;
+  try {
+    sessionStorage.setItem(
+      SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL,
+      window.location.href,
+    );
+  } catch {
+    // ignore storage failures; redirect should still proceed
+  }
   window.location.replace(new URL("authenticate/", baseApiUrl()).href);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/frontend/apps/calendars/src/features/api/fetchApi.ts` around lines 32 -
38, The code sets the module-level flag redirectInFlight before writing to
sessionStorage which can throw and leave redirectInFlight true permanently;
change the logic in the 401 handling around
redirectInFlight/SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL so that
sessionStorage.setItem is attempted inside a try/catch and redirectInFlight is
only set after a successful write (or set regardless if the write fails), and
always call window.location.replace(new URL("authenticate/", baseApiUrl()).href)
in the finally/error path; specifically update the block that references
redirectInFlight, sessionStorage.setItem,
SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL, and
window.location.replace/baseApiUrl() so a thrown storage error does not prevent
future redirects.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/frontend/apps/calendars/package.json`:
- Line 35: Update the dependency entry for xml-js in package.json to pin it to
an exact version instead of a caret range: replace the semver spec "^1.6.11" for
"xml-js" with the exact version "1.6.11" so installs are reproducible and
consistent with the rest of the file.
- Line 35: The dependency "xml-js": "^1.6.11" in package.json is old (last
published 2019) so confirm its acceptability for CalDAV parsing by: 1) running
Snyk/OSV/npm audit to verify no advisories for xml-js@1.6.11, 2) documenting the
outcome (keep or replace) in the repo (e.g., dependency decision note), and 3)
if you choose to replace, swap xml-js with a maintained XML library (e.g.,
fast-xml-parser) and update all CalDAV parsing code that imports/uses xml-js to
the new parser APIs; reference the "xml-js" entry in package.json and the CalDAV
parsing modules when making changes.

In
`@src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts`:
- Around line 1100-1103: Remove the now-unused sourceCalendar variable and its
no-op suppression from CalDavService: delete the sourceCalendar variable
declaration/assignment (the earlier assignment that was only used for fallback
semantics) and remove the `void sourceCalendar` line where it was used to
silence warnings; ensure any logic relying on davRequest and shared session auth
remains intact (refer to symbols sourceCalendar, davRequest and class
CalDavService to locate the affected code).

---

Outside diff comments:
In `@src/frontend/apps/calendars/src/features/api/fetchApi.ts`:
- Around line 32-38: The code sets the module-level flag redirectInFlight before
writing to sessionStorage which can throw and leave redirectInFlight true
permanently; change the logic in the 401 handling around
redirectInFlight/SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL so that
sessionStorage.setItem is attempted inside a try/catch and redirectInFlight is
only set after a successful write (or set regardless if the write fails), and
always call window.location.replace(new URL("authenticate/", baseApiUrl()).href)
in the finally/error path; specifically update the block that references
redirectInFlight, sessionStorage.setItem,
SESSION_STORAGE_REDIRECT_AFTER_LOGIN_URL, and
window.location.replace/baseApiUrl() so a thrown storage error does not prevent
future redirects.

In
`@src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts`:
- Around line 40-58: Remove the unused import parseSharePrivilege from the
import list at the top of CalDavService.ts (the import that pulls from
'./caldav-helpers'); update the import statement that currently includes
parseSharePrivilege alongside buildProppatchXml, buildShareRequestXml, etc., to
no longer reference parseSharePrivilege and run the linter/TypeScript compile to
confirm no other references to parseSharePrivilege remain.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9c919bd6-a3c0-4808-9472-cdd73d4f8a07

📥 Commits

Reviewing files that changed from the base of the PR and between 44800db and 4ef7cbc.

⛔ Files ignored due to path filters (1)
  • src/frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (28)
  • .gitignore
  • src/frontend/Dockerfile
  • src/frontend/apps/calendars/package.json
  • src/frontend/apps/calendars/src/features/api/fetchApi.ts
  • src/frontend/apps/calendars/src/features/calendar/contexts/CalendarContext.tsx
  • src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/VCardComponent.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/CalDavService.connect.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/CalDavService.moveEvent.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/caldav-helpers.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/event-calendar-helper.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/ics-helper.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/__tests__/timezone-conversion.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/caldav-helpers.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/dav-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/event-calendar-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/ics-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/index.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/types-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/caldav-service.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts
  • src/frontend/apps/calendars/src/features/calendar/utils/DavClient.ts
  • src/frontend/apps/calendars/src/features/calendar/utils/__tests__/DavClient.test.ts
  • src/frontend/apps/calendars/src/features/resources/api/useResourcePrincipals.ts
  • src/frontend/apps/calendars/src/features/settings/api/useWorkingHours.ts
  • src/frontend/apps/calendars/src/styles/globals.scss
💤 Files with no reviewable changes (13)
  • src/frontend/apps/calendars/src/features/calendar/services/dav/tests/event-calendar-helper.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/calendar.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/tests/ics-helper.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/addressbook.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/tests/timezone-conversion.test.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/dav-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/ics-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/index.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/VCardComponent.ts
  • src/frontend/apps/calendars/src/styles/globals.scss
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/types-helper.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/types/options.ts
  • src/frontend/apps/calendars/src/features/calendar/services/dav/helpers/event-calendar-helper.ts

Comment thread src/frontend/apps/calendars/package.json Outdated
Comment thread src/frontend/apps/calendars/src/features/calendar/services/dav/CalDavService.ts Outdated
@sylvinus sylvinus merged commit cf83793 into main May 30, 2026
8 checks passed
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