webdav-client
Promise-based TypeScript WebDAV client for Node.js, browsers, and React Native.
Repository Health
Technical Analysis
webdav is a TypeScript client library for the WebDAV protocol, giving Node.js, browser, and React Native applications a single promise-based API for interacting with any WebDAV-compliant remote filesystem — including Nextcloud, ownCloud, Box, and Yandex Disk. Instead of hand-rolling PROPFIND/XML parsing and raw HTTP requests, consumers call createClient(url, options) once and get back methods for directory listings, file reads/writes, streaming, locking, and quota checks.
The library is used in production by projects like the Buttercup password manager and Nextcloud’s own Server and Photos apps, and ships dual builds (Node and web/React Native) from one TypeScript codebase, with pluggable authentication (none, basic, digest, OAuth token) and extension points for custom server-specific XML properties.
What You Get
- A single createClient(url, options) factory returning promise-based methods for every core WebDAV operation — no classes to instantiate or connections to manage manually.
- Cross-platform builds for Node.js, browsers, and React Native shipped from one codebase, so the same API works across server and client code.
- Structured, typed errors via Layerr with a stable ErrorCode enum instead of opaque HTTP failures.
- Extension points — registerAttributeParser, registerTagParser, and getPatcher() — for consuming custom WebDAV properties (e.g. Nextcloud share attributes) or swapping the transport layer.
Common Use Cases
- Building a file-sync or backup client against Nextcloud, ownCloud, Box, or Yandex Disk WebDAV endpoints.
- Adding remote file browsing/upload UI to a web or React Native app without writing raw HTTP/XML PROPFIND handling.
- Powering a password manager or note-taking app (as used by Buttercup) that needs a self-hosted, provider-agnostic storage backend.
Under The Hood
Architecture createClient in source/factory.ts builds a single WebDAVClientContext (auth type, headers, remote path/URL, parsing config) via setupAuth (source/auth/index.ts), then returns a plain object whose methods are thin closures delegating to independent operation modules under source/operations/ (copyFile, createDirectory, createStream, deleteFile, directoryContents, exists, getFileContents, getQuota, lock, moveFile, putFileContents, partialUpdateFileContents, getDAVCompliance, search, stat). Each operation composes request.ts’s prepareRequestOptions/request (wrapping @buttercup/fetch, handling digest/basic/oauth auth and node/web/react-native branching via compat/env.ts) with response.ts’s handleResponseCode/processResponsePayload and tools/dav.ts’s XML/PROPFIND parsing built on fast-xml-parser. There is no class hierarchy or DI container — it is a functional, context-passing design where WebDAVClientContext is threaded explicitly through every call, which keeps the core testable and swappable (getPatcher() in compat/patcher.ts lets consumers monkey-patch the transport) at the cost of every operation module needing to agree on the shared context shape.
Tech Stack TypeScript compiled to dual Node/browser/React Native outputs (dist/node, dist/web, dist/react-native) via tsc for Node and webpack 5 with babel-loader for the web bundle. Runtime dependencies are minimal and single-purpose: @buttercup/fetch for cross-platform fetch, fast-xml-parser for PROPFIND/XML, layerr for structured errors, minimatch for pattern matching, url-join/url-parse/path-posix for path handling, and md5/byte-length for content hashing and length calculation. Development tooling centers on vitest 4 split across three “projects” (node-unit, browser, node-types), Playwright for browser end-to-end specs, prettier with husky/lint-staged for pre-commit formatting, and npm-run-all/concurrently to orchestrate the multi-target build and test scripts. The package.json’s “type”: “module” plus a per-entrypoint exports map (node/web/react-native/dist/*) reflects a deliberately engineered multi-target ESM package.
Code Quality Tests live under test/node, test/web, and test/types, backed by real fixture data (test/responses/, test/serverContents/) covering edge cases like numeric displaynames, HTML-entity-encoded hrefs, nginx 404 bodies, and Seafile PROPFIND quirks, plus a spun-up webdav-server instance for integration-style coverage in test/server. CI (.github/workflows/test.yml) runs the full vitest matrix across Node 18/20/22/24, a dedicated lint/format job, and a Playwright-driven browser-specs job. Source modules are consistently typed against exported interfaces in types.ts, use Layerr with a coded ErrorCode enum rather than bare thrown strings, and prettier plus lint-staged enforce formatting before every commit — no test files were skipped or found missing across the operations or auth layers.
API Design createClient(url, options) returns one flat object with a single method per WebDAV verb (copyFile, getFileContents, putFileContents, lock/unlock, getQuota, search, stat, getDAVCompliance, plus customRequest as an escape hatch) — all promise-based with a consistent (path, options) signature. An optional {details: true} flag switches any read method to return headers/status alongside the parsed body without introducing a second parallel API. Escape hatches beyond the core surface — registerAttributeParser/registerTagParser for server-specific XML properties, a pluggable entityDecoder, and getPatcher() for transport-level monkey-patching — go further than a typical thin protocol wrapper, though the underlying protocol handling itself is standard rather than novel.
Used by 3 apps in this directory
Cherry Studio
AI Assistants
All-in-one AI desktop client with 300+ assistants and multi-model support
Rocket.Chat
Team Chat
The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.
Nextcloud Server
Collaboration · File Storage
Your own private cloud: self-hosted file sync, collaboration, and communication with no vendor lock-in.