tsdav

repository·main·Indexed 43 days ago

https://github.com/natelindev/tsdav

A 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.

Tokens
45K
Snippets
137
Records
197
Agent score
56%

What's inside tsdav

  1. Understand the DAVDepth type

    main

    The 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.

    DepthAction 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';
  2. Understand WebDAV operations and mental models

    main

    WebDAV uses XML for data communication. Understanding its structure is essential for working with its providers:

    Core Concepts

    • Hierarchy: A WebDAV server has accounts. An account has a principal resource (the main/default resource). Under the principal, there is a home set where actual resources reside.
    • Objects & Collections: The basic element is an object. Multiple objects form a collection.
    • Change Tracking: syncToken and ctag act as hashes for objects or collections; they change whenever the contents change.
    • CalDAV: Calendar data uses the rfc5545 iCal format. Use iCal2Js and js2iCal (often via the pretty-jcal project) to convert between iCal and JavaScript objects.

    WebDAV vs REST Operations

    OperationWebDAV MethodREST EquivalentNotes
    Create collectionMKCOL /entities/$predefined_idPOST /entitiesWebDAV requires a predefined ID; REST returns a new ID.
    Create entityPUT /entities/$predefined_id (with body) or POST /entities (no ID)POST /entitiesWebDAV may require a subsequent PROPPATCH to set attributes.
    Update bodyPUT /entities/$predefined_idPUT (Full) or PATCH (Partial)WebDAV PUT typically updates the body without attributes.
    Update attributesPROPPATCH /entities/$idPUT or PATCHWebDAV uses PROPPATCH with an XML body for attribute changes.
    Delete entityDELETE /entities/$idDELETE /entities/$idBoth return 204 No Content.
    List entitiesPROPFIND /entitiesGET /entitiesWebDAV returns a 207 Multi-Status XML response.
    Get entityGET /entities/$idGET /entities/$idReturns the entity body.
    Get attributesPROPFIND /entities/$idGET /entities/$idWebDAV returns a 207 Multi-Status XML response.
  3. Understand the DAVAddressBook type

    main

    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;
  4. Compare `syncCalendars` vs `syncCalendarsDetailed`

    main

    Choosing between the two sync methods depends on whether you need the actual calendar events (objects) or just the status of the calendars themselves.

    FeaturesyncCalendarssyncCalendarsDetailed
    Primary GoalGet the latest list of calendars AND their updated objects.Identify which calendars were created, updated, or deleted.
    Return TypeArray<DAVCalendar>{ created: Array<DAVCalendar>, updated: Array<DAVCalendar>, deleted: Array<DAVCalendar> }
    Object PayloadIncludes latest objects for updated calendars.Returns calendars without objects.
    Input RequirementoldCalendars must include objects.oldCalendars does not need objects.
  5. Understand the DAVVCard type

    main

    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;
  6. Handle Digest and Custom authentication

    main

    Digest Authentication

    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.

    Custom Authentication

    To implement custom authentication logic, use the DAVCredentials object:

    1. Pass additional data via the customData property.
    2. Provide a custom authentication function via the authFunction parameter. This function will have access to the DAVCredentials instance.
  7. CardDAV workflow: Managing contacts

    main

    CardDAV workflows follow a pattern similar to CalDAV for managing address books and VCards:

    • Discovery: fetchAddressBooks finds available address books.
    • Retrieval: fetchVCards, addressBookMultiGet, and addressBookQuery return contact payloads.
    • CRUD Operations: createVCard, updateVCard, and deleteVCard manage .vcf resources. Note that these helpers honor provider-specific UID behaviors.
  8. How WebDAV discovery and requests work

    main

    The library uses several building blocks to locate and interact with WebDAV accounts:

    • Discovery: serviceDiscovery, fetchPrincipalUrl, and fetchHomeUrl use /.well-known/ redirects to locate account roots.
    • Account Creation: createAccount takes a DAVAccount and enriches it with discovered URLs and calendars/address books using provided credentials.
    • Low-level Requests: davRequest is the core fetch wrapper used by all high-level CalDAV and CardDAV helpers.
    • Object Management:
      • createObject, updateObject, and deleteObject handle PUT/PATCH/DELETE operations with concurrency headers.
      • propfind is used to read WebDAV metadata.
  9. Syncing and Updating Imported iCal Events

    main

    When implementing an iCal feed importer with tsdav, consider the following for maintaining data integrity:

    • Avoiding Duplicates: Track imported event UIDs (e.g., in a local database or map) to ensure you don't upload the same event multiple times.
    • Handling Updates: If an event in the source feed changes, use updateCalendarObject instead of createCalendarObject to modify the existing entry on the CalDAV server.
    • Polling: 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.
  10. CalDAV workflow: Managing calendars and objects

    main

    CalDAV workflows allow for calendar enumeration and object manipulation:

    • Enumeration: Use fetchCalendars to list available calendars.
    • Retrieval: Use fetchCalendarObjects, calendarMultiGet, or calendarQuery to get calendar data.
    • CRUD Operations: createCalendarObject, updateCalendarObject, and deleteCalendarObject manage resources while enforcing If-Match/If-None-Match headers for concurrency control.
    • Synchronization: syncCalendars and smartCollectionSync utilize server-side sync-token/ctag deltas to perform incremental updates.