yatta/webdav
WebDAV over any store: methods, locks, PROPFIND, downloads.
7 exported symbols and 24 members, read from src/func/webdav.ts.
Construct
createStorageDavStore
functionBack WebDAV with the Yatta storage engine.
A key-value store has no real folders, so a collection is recorded as a marker file, `<path>/.dav-collection`. The name is reserved: a client cannot create, read, overwrite or list it as an ordinary file.
createStorageDavStore(storage: { upload(key: string, data: Uint8Array, options?: { contentType?: string; }): Promise<unknown>; download(key: string): Promise<{ arrayBuffer(): Promise<ArrayBuffer>; contentType: string; lastModified: Date; }>; head(key: string): Promise<{ size: number; contentType: string; lastModified: Date; }>; delete(key: string): Promise<void>; copy(src: string, dst: string): Promise<unknown>; move(src: string, dst: string): Promise<unknown>; exists(key: string): Promise<boolean>; list(options?: { prefix?: string; }): Promise<Array<{ path: string; size: number; contentType: string; lastModified: Date; }>>; }): DavStore- storage
- Anything shaped like `yatta.js/storage`'s engine — the same object, not an adapter around it.
createWebDAVHandler
functionBuild the WebDAV handler for a store.
createWebDAVHandler(store: DavStore, options?: WebDAVOptions): (req: Request) => Promise<Response>- store
- Where the bytes live. Use `createStorageDavStore(storage)` to back it with the Yatta storage engine, or your own for tests.
Returns A `(req) => Promise<Response>` for a router or `Bun.serve`.
DavError
classAn error with an HTTP status, for a store that needs to say no.
`throw new DavError(403, "reserved name")` reaches the client as that status and message. Any other thrown error is logged and answered 500, so an internal detail never becomes the response body.
class DavError extends Error1 member
statuspropertystatus: number
Types
DavEntry
interfaceOne path in the tree, with the metadata PROPFIND reports.
interface DavEntry5 members
pathpropertypath: stringisCollectionpropertyisCollection: booleansizepropertysize: numberlastModifiedpropertylastModified: DatecontentTypepropertycontentType?: string
DavFile
interfaceA file as the store returns it: the bytes plus what a browser needs.
interface DavFile3 members
bodypropertybody: Uint8ArraycontentTypepropertycontentType: stringlastModifiedpropertylastModified: Date
DavStore
interfaceThe small surface the handler needs from a backing store.
Paths never start with "/" and the root collection is `""`. Copy and move a whole collection only turn up as a `mkdir` plus per-file calls, except `move` on a single file, so a store that can rename cheaply should — reading a large file into memory to move it is the handler's fallback, not a requirement.
interface DavStore10 members
getget(path: string): Promise<DavFile | null>putput(path: string, body: Uint8Array, contentType?: string): Promise<void>deletedelete(path: string): Promise<boolean>existsexists(path: string): Promise<boolean>isCollectionisCollection(path: string): Promise<boolean>listlist(path: string): Promise<DavEntry[]>mkdirmkdir(path: string): Promise<void>copycopy(src: string, dst: string): Promise<void>movemove(src: string, dst: string): Promise<void>statstat(path: string): Promise<DavEntry | null>?
WebDAVOptions
interfaceHow the handler behaves. Everything is optional; the defaults are a
interface WebDAVOptions5 members
basePathpropertybasePath?: stringdefaultLockMspropertydefaultLockMs?: numberauthenticatepropertyauthenticate?: (req: Request) => Promise<boolean | Response> | boolean | ResponsereadOnlypropertyreadOnly?: booleanmaxBodyBytespropertymaxBodyBytes?: number
AuthConfig or JobPayload — declaring your schema once is enough for the rest to follow. See Typed keys.