Skip to main content
Version: 2.3.2

Contributing

Use Node.js 22.12+ for development and tests (Vitest 5 requires it). The published library continues to support Node.js 18+.

First you need to clone the repo and install dependencies with pnpm install. The repo pins pnpm 10.34.4 for local, CI, and Vercel builds. Vercel installs the docs package with pnpm install --frozen-lockfile.

Build

Building release artifacts uses Rolldown and requires Node.js 20.19+ or 22.12+.

pnpm build

Test

Run pnpm test:unit for the unit suite; it does not require provider credentials.

For live provider integration tests, configure a .env file from .env.example:

cp .env.example .env

and fill in the missing values

If you didn't add any new api, you should set MOCK_FETCH="true". If you added new api and need to test against cloud providers, you should set MOCK_FETCH="false" and RECORD_NETWORK_REQUESTS="true" to updated network request mock data.

Docs dependency verification

Run pnpm --dir docs test to verify the image parser used by Docusaurus. These tests run malformed images in child processes with timeouts, and also check valid image dimensions through CommonJS, ESM, buffer, and file APIs.

The docs package overrides image-size with image-size-next@2.1.1, a compatible fork that fixes CVE-2025-71329 and CVE-2025-71330. Keep the override until Docusaurus depends on a fixed parser; removing it would reintroduce the vulnerable upstream package. See the fork's changelog.

WEBDAV quick guide

WEBDAV uses xml for all its data when communicating, the basic element is object, multiple objects can form a collection, webdav server have accounts and an account have a principal resource (i.e the default, main resource) and under that principal resource we have home set of the said resource where your actual resources are.

syncToken and ctag are basically like hash of the object/collection, if anything in it changes, this token will change.

For caldav, the calendar data in caldav are in rfc5545 ical format, there's iCal2Js and js2iCal function with my other project pretty-jcal to help your convert them from/to js objects.

Here's cheat sheet on webdav operations compared with rest:

OperationWebdavREST
Create collection
  • predefined id: MKCOL /entities/$predefined_id
  • no predefined id: not possible
  • can set attributes right away with extended-mkcol extension
  • Status: 201 Created
  • POST /entities with JSON body with attributes, response contains new id
  • Status: 200 with new id and optionally the whole object
Create entity
  • predefined id: PUT /entities/$predefined_id with body, empty response
  • no predefined id: POST /entities, receive id as part of Content-Location header
  • can't set attributes right away, need subsequent PROPPATCH
  • Status: 201 Created
Update entity body
  • PUT /entities/$predefined_id with new body (no attributes)
  • Status: 204 No Content
  • Full: PUT /entities/$id with full JSON body with attributes
  • Status 200, receive full object back
  • Partial: PATCH /entities/$id with partial JSON containing only attributes to update.
  • Status 200, full/partial object returned
Update entity attributes
  • PROPPATCH /entities/$id with XML body of attributes to change
  • Status: 207, XML body with accepted attributes
Delete entity
  • DELETE /entities/$id
  • Sattus: 204 no content
List entities
  • PROPFIND /entities with XML body of attributes to fetch
  • Status 207 multi-status XML response with multiple entities and their respective attributes
  • GET /entities
  • Status: 200 OK, receive JSON response array with JSON body of entity attributes
Get entity
  • GET /entities/$id
  • Status: 200 OK with entitiy body
  • GET /entities/$id
  • Status 200 OK, receive JSON body of entity attributes
Get entity attributes
  • PROPFIND /entities/$id with XML body of attributes to fetch
  • Status 207 multi-status XML response with entity attributes
Notes
  • cannot always set attributes right away at creation time, need subsequent PROPPATCH
  • no concept of body vs attributes
  • entity can be either collection or model (for collection /entities/$collectionId/$itemId)