# Storage

The client API for user file uploads. It works in local dev. File storage for hosted folds is not available yet.

## Status

| Where | Uploads |
|---|---|
| `npx @aozumi/fold dev` | Work. Files are kept in memory and are lost when the dev server restarts. |
| Hosted at `*.aozumi.site` | **Coming soon.** Every storage request answers `501` with `{ "error": "File storage for hosted folds is coming soon." }`. |

On a hosted fold, `client.storage.upload()` rejects with an error whose message is `Storage request failed (501).`, `code` is `"unavailable"`, and `status` is `501`. Do not build a feature that depends on uploads into a fold you deploy today. Small text belongs in the database instead (up to 64 KiB per field, 1 MB per anonymous fold).

## API

```tsx
import { createClient } from "@aozumi/fold/client";
import type app from "../server/index";

const client = createClient<typeof app>();

export function AvatarUpload() {
  async function onChange(event: Event) {
    const file = (event.currentTarget as HTMLInputElement).files?.[0];
    if (!file) {
      return;
    }
    try {
      const uploaded = await client.storage.upload(file, { public: true });
      console.log(uploaded.url, uploaded.key, uploaded.size, uploaded.contentType);
    } catch (error) {
      console.error(error);
    }
  }
  return <input type="file" accept="image/*" onChange={(event) => void onChange(event)} />;
}
```

The same object is exported directly as `storage` from `@aozumi/fold/client`.

| Member | Signature |
|---|---|
| `upload` | `(file: Blob, options?: { public?: boolean }) => Promise<UploadedObject>` |
| `delete` | `(key: string) => Promise<void>` |

`UploadedObject` is `{ contentType: string; key: string; size: number; url: string }`.

- The caller must have a session (guest or signed in). Otherwise `upload` throws.
- `public: true` gives a URL anyone can load, for example in `<img src>`. Without it the object is private to its uploader.
- Store `key` in the database if you need to delete the file later.

## Rules in local dev

- Up to 5 MiB per file.
- Browser-active and executable types are refused, such as `text/html`, JavaScript, and Windows executables.
- Data resets on dev server restart.

The CLI can manage local files with `npx @aozumi/fold storage list|get|put|delete --port 3000`. See [CLI](/fold/cli/).

## Server side

There is no storage API inside server handlers. `ctx` has no storage member. The `@aozumi/fold/storage` entry point exports the hosting side of storage (request handling, providers, ledgers), not an API for app code. App code may only import `@aozumi/fold/server` and `@aozumi/fold/client`.
