Svelte
The full Files API in the browser, idiomatic Svelte - useFiles returns the verbs plus Svelte stores for ambient state (read with $store), with useList / useFile / useSearch.
files-sdk/svelte brings the full Files API to the browser as idiomatic Svelte. useFiles returns one method per Files verb — upload, download, url, list, and the rest — plus ambient upload/error state as Svelte stores you read with the $ prefix.
<script lang="ts">
import { useFiles } from "files-sdk/svelte";
import { onDestroy } from "svelte";
const files = useFiles({ endpoint: "/api/files" });
const { isUploading, progress, error } = files;
onDestroy(files.abort); // cancel any in-flight calls on unmount
async function onUpload(event: Event) {
const file = (event.currentTarget as HTMLInputElement).files?.[0];
if (file) {
await files.upload(file);
}
}
</script>
<input type="file" on:change={onUpload} />
{#if $isUploading}<progress value={$progress.fraction} />{/if}
{#if $error}<p>{$error.message}</p>{/if}The binding ships no Svelte runtime — its stores are a tiny implementation of the store contract, so $store auto-subscription works exactly as with writable.
The verbs
Every verb mirrors the SDK — upload, download, head, exists, list, listAll, search, url, delete, copy, move, signedUploadUrl, capabilities — including the bulk array forms. They are plain methods:
const { key } = await files.upload(file); // keyless → server mints the key
const stored = await files.download("report.pdf"); // → a lazy StoredFile
const link = await files.url("avatar.png"); // → string, for <img src>
await files.delete(["a.txt", "b.txt"]); // bulk → { deleted, errors? }Ambient state (stores)
files.isUploading; // Readable<boolean> → $isUploading
files.progress; // Readable<{ loaded, total, fraction }>
files.uploads; // Readable<FileUploadState[]> — per-file live state
files.error; // Readable<FilesError | undefined> — last error from any verb
files.reset(); // clear ambient error + upload state (re-arms after abort)
files.abort(); // abort every in-flight call — wire to onDestroySvelte's lifecycle hooks need the compiler, so cancel in-flight work by calling files.abort from onDestroy — one line, as above.
Reactive reads
The query stores load on creation and expose data / error / isLoading / isFetching stores plus refetch(). Svelte's reactivity lives at the component level, so re-run them from a $: block when a dependency changes:
<script lang="ts">
import { useList } from "files-sdk/svelte";
let prefix = "docs/";
const { data, isLoading, refetch } = useList({ prefix });
$: prefix, refetch(); // re-run whenever `prefix` changes
</script>
{#if $isLoading}Loading…{:else}
<ul>{#each $data?.items ?? [] as item}<li>{item.key}</li>{/each}</ul>
{/if}useFile(key) (a head() for previews) and useSearch(pattern, opts) work the same way.
Setting up the gateway
Point the binding at a mounted gateway — createFilesRouter on Next, Hono, Express, or any Web-Request runtime — and lock it down with authorize.
React
One hook, every Files verb. Imperative methods with upload progress and ambient error state, plus optional reactive useList / useFile / useSearch.
Vue
The full Files API in the browser as a Vue 3 composable - useFiles returns the verbs plus refs for ambient state, with reactive useList / useFile / useSearch.