nextcloud-files
TypeScript helpers for building Nextcloud Files app integrations: WebDAV client, file/folder model, UI registry, and uploader.
Repository Health
Technical Analysis
@nextcloud/files is the official TypeScript toolkit Nextcloud apps use to work with files and the Files app UI. It wraps the WebDAV protocol into a Nextcloud-aware client, models files and folders as typed Node/File/Folder objects with proxy-guarded attributes, and exposes a framework-agnostic registry so any app — Vue, vanilla JS, or otherwise — can add file actions, list filters, sidebar tabs, and new-menu entries to the Files app.
A separate upload entry point ships a shared, chunked Uploader with typed error handling and public-share support, while the dav entry point provides low-level WebDAV helpers (getClient, resultToNode, getFavoriteNodes) for listing, favoriting, and syncing content. Maintained by Nextcloud GmbH as one of the nextcloud-libraries packages that underpin the core Files app, it is the de facto dependency for any first- or third-party app that needs to read, write, or extend file browsing in Nextcloud.
What You Get
- A typed WebDAV client (
getClient,resultToNode,getFavoriteNodes) that maps DAV multistatus responses ontoNodeobjects - A
Node/File/Folderobject model with proxy-guarded, read-only computed attributes (source, basename, mtime, permissions) - A framework-agnostic Files app UI registry for file actions, list actions, list filters, list headers, and new-menu entries
- Web-component-based sidebar tab registration with a documented Vue
defineCustomElementbridge - A shared, chunked
Uploadersingleton withp-queueconcurrency, typed upload errors, and public-share support - Filename/path validation and unique-name generation helpers for safe renames and uploads
Common Use Cases
- Registering a custom file action or “New”-menu entry so a third-party app can create or act on files from the Files app
- Adding a custom sidebar tab (e.g. sharing details, metadata) via a native web component, usable from any frontend framework
- Listing, favoriting, or syncing a folder’s contents by querying WebDAV and converting results into typed
Nodeobjects - Queuing chunked uploads (authenticated or public-share) with progress tracking and typed error handling
Under The Hood
Architecture
The library is organized into four cohesive domains, each its own public entry point declared in package.json exports: node/ (the Node/File/Folder class hierarchy with a Proxy-wrapped attributes object enforcing read-only computed properties and mtime updates), dav/ (a WebDAV client wrapper around the webdav package that converts DAV multistatus responses into Node instances via resultToNode/getFavoriteNodes), ui/ (a global FilesRegistry singleton extending a typed EventTarget for registering file actions, list actions, filters, headers, and sidebar tabs), and upload/ (an Uploader class exposed through a global getUploader() singleton with chunking and typed errors). Data flows one way: WebDAV responses become Node instances, which are then handed to UI registry consumers that mutate attributes only through the proxy-guarded setter, keeping invariants like readonly computed properties intact. Because the Node model is the single boundary both dav/ (producer) and ui/ (consumer) depend on, it is the module most third-party code implicitly couples to.
Tech Stack
Written almost entirely in TypeScript (ESM-only, "type": "module"), built with Vite via @nextcloud/vite-config’s createLibConfig into three separate bundles (index, dav, upload) with generated declaration files, plus a typedoc script for hosted API docs. Runtime dependencies are exclusively first-party Nextcloud helper packages (@nextcloud/auth, @nextcloud/axios, @nextcloud/capabilities, @nextcloud/l10n, @nextcloud/logger, @nextcloud/paths, @nextcloud/router, @nextcloud/sharing) alongside general-purpose utilities: webdav for the DAV protocol, axios-retry, is-svg, p-queue for upload concurrency, and typescript-event-target for the typed registry event target. Despite backing a Vue-based frontend, the library itself has no UI framework dependency — integration is via framework-agnostic web components.
Code Quality
34 .spec.ts test files live both under a top-level __tests__/ directory and colocated with source (e.g. getUploader.spec.ts), run through Vitest with @vitest/browser-playwright for browser-style DAV/uploader tests against a real @nextcloud/e2e-test-server, and @vitest/coverage-istanbul feeding Codecov. TypeScript runs in strict mode (with noImplicitAny: false the one relaxation) via a dedicated ts:check script, and ESLint runs the shared @nextcloud/eslint-config “recommendedLibrary” preset. Both are enforced as separate required CI jobs alongside a REUSE license-header check and Dependabot auto-merge automation, indicating a disciplined, actively maintained pipeline. Upload failures use dedicated typed error classes rather than generic exceptions.
What Makes It Unique
Rather than shipping Vue components for Files app extension points, the UI integration surface (getFilesRegistry, sidebar tabs, file actions/filters/headers) is deliberately framework-agnostic, built on native CustomEvent/EventTarget and web components so apps written in Vue, vanilla JS, or any other framework can extend the Files app without adopting Vue as a hard dependency — the README documents an explicit defineCustomElement-based bridge for Vue consumers who still want reactive components. The object model’s use of a Proxy to enforce read-only computed attributes at the object level, rather than generating getter/setter boilerplate per field, is a clean, uncommon touch for this kind of domain model.