Supported Runtimes for tsdav
maintsdav is compatible with the following environments:
Browsers(note: check CORS requirements)Node.js(>= 18)BunDenoCloudflare Workers
repository·main·Indexed 43 days ago
https://github.com/natelindev/tsdavA TypeScript-first WebDAV, CALDAV, and CARDDAV client for Node.js (>= 18), Browsers, Bun, Deno, and Cloudflare Workers. Version 2.3.3 provides a JSON-based API and supports OAuth2, Basic, and Bearer token authentication. It includes high-level helpers for calendar and contact management, including synchronization via sync-tokens and ctags, as well as low-level WebDAV request utilities.
tsdav is compatible with the following environments:
Browsers (note: check CORS requirements)Node.js (>= 18)BunDenoCloudflare WorkersThe DAVDepth type defines the depth of a WebDAV request, determining which resources are affected by an action. It is used to control whether an operation applies only to a specific resource, its immediate members, or all members recursively.
| Depth | Action applies to |
|---|---|
'0' | Only the resource itself |
'1' | The resource and its immediate internal members only |
'infinity' | The resource and all its members (recursively) |
export type DAVDepth = '0' | '1' | 'infinity';WebDAV uses XML for data communication. Understanding its structure is essential for working with its providers:
accounts. An account has a principal resource (the main/default resource). Under the principal, there is a home set where actual resources reside.object. Multiple objects form a collection.syncToken and ctag act as hashes for objects or collections; they change whenever the contents change.rfc5545 iCal format. Use iCal2Js and js2iCal (often via the pretty-jcal project) to convert between iCal and JavaScript objects.| Operation | WebDAV Method | REST Equivalent | Notes |
|---|---|---|---|
| Create collection | MKCOL /entities/$predefined_id | POST /entities | WebDAV requires a predefined ID; REST returns a new ID. |
| Create entity | PUT /entities/$predefined_id (with body) or POST /entities (no ID) | POST /entities | WebDAV may require a subsequent PROPPATCH to set attributes. |
| Update body | PUT /entities/$predefined_id | PUT (Full) or PATCH (Partial) | WebDAV PUT typically updates the body without attributes. |
| Update attributes | PROPPATCH /entities/$id | PUT or PATCH | WebDAV uses PROPPATCH with an XML body for attribute changes. |
| Delete entity | DELETE /entities/$id | DELETE /entities/$id | Both return 204 No Content. |
| List entities | PROPFIND /entities | GET /entities | WebDAV returns a 207 Multi-Status XML response. |
| Get entity | GET /entities/$id | GET /entities/$id | Returns the entity body. |
| Get attributes | PROPFIND /entities/$id | GET /entities/$id | WebDAV returns a 207 Multi-Status XML response. |
In tsdav, DAVAddressBook is a type alias for DAVCollection. It represents a collection of address book entries within a WebDAV environment. Because it is an alias, all properties, methods, and behaviors associated with DAVCollection apply to DAVAddressBook.
export type DAVAddressBook = DAVCollection;fetchCalendarObjects uses calendarMultiGet (via the useMultiGet: true option). However, some calendar providers do not support calendarMultiGet. In such cases, set useMultiGet: false to force the function to use calendarQuery instead.Choosing between the two sync methods depends on whether you need the actual calendar events (objects) or just the status of the calendars themselves.
| Feature | syncCalendars | syncCalendarsDetailed |
|---|---|---|
| Primary Goal | Get the latest list of calendars AND their updated objects. | Identify which calendars were created, updated, or deleted. |
| Return Type | Array<DAVCalendar> | { created: Array<DAVCalendar>, updated: Array<DAVCalendar>, deleted: Array<DAVCalendar> } |
| Object Payload | Includes latest objects for updated calendars. | Returns calendars without objects. |
| Input Requirement | oldCalendars must include objects. | oldCalendars does not need objects. |
In tsdav, DAVVCard is a type alias for DAVObject. It represents a standard data object within the DAVV ecosystem. When working with card-based data structures, you can use DAVVCard interchangeably with DAVObject to ensure type safety for your data objects.
export type DAVVCard = DAVObject;For Digest authentication, you must handle the challenge-response process yourself. Pass the final generated digest string (containing username, realm, nonce, uri, qop, nc, cnonce, response, and opaque) as the digestString parameter in DAVCredentials.
To implement custom authentication logic, use the DAVCredentials object:
customData property.authFunction parameter. This function will have access to the DAVCredentials instance.CardDAV workflows follow a pattern similar to CalDAV for managing address books and VCards:
fetchAddressBooks finds available address books.fetchVCards, addressBookMultiGet, and addressBookQuery return contact payloads.createVCard, updateVCard, and deleteVCard manage .vcf resources. Note that these helpers honor provider-specific UID behaviors.The library uses several building blocks to locate and interact with WebDAV accounts:
serviceDiscovery, fetchPrincipalUrl, and fetchHomeUrl use /.well-known/ redirects to locate account roots.createAccount takes a DAVAccount and enriches it with discovered URLs and calendars/address books using provided credentials.davRequest is the core fetch wrapper used by all high-level CalDAV and CardDAV helpers.createObject, updateObject, and deleteObject handle PUT/PATCH/DELETE operations with concurrency headers.propfind is used to read WebDAV metadata.When implementing an iCal feed importer with tsdav, consider the following for maintaining data integrity:
updateCalendarObject instead of createCalendarObject to modify the existing entry on the CalDAV server.tsdav does not automatically poll feeds. You must implement a periodic task (such as a cron job or background worker) to trigger the fetch-parse-push cycle.CalDAV workflows allow for calendar enumeration and object manipulation:
fetchCalendars to list available calendars.fetchCalendarObjects, calendarMultiGet, or calendarQuery to get calendar data.createCalendarObject, updateCalendarObject, and deleteCalendarObject manage resources while enforcing If-Match/If-None-Match headers for concurrency control.syncCalendars and smartCollectionSync utilize server-side sync-token/ctag deltas to perform incremental updates.