Drive
Available since v0.48.0
Drive is the app’s file storage. Like the KV store, it belongs to the app and everyone the app reaches sees the same files. Use KV for structured data and Drive for bytes.
interface MaypopDriveFile { id: string; cid: string; name: string; mimeType: string | null; size: number | null; uploadedBy: string; createdAt: string;}
interface MaypopDrive { readonly maxUploadBytes: number; list(opts?: { prefix?: string }): Promise<MaypopDriveFile[]>; stat(name: string): Promise<MaypopDriveFile | null>; read(name: string): Promise<string>; readBlob(name: string): Promise<Blob>; write( name: string, content: string | Blob | ArrayBuffer | ArrayBufferView, ): Promise<MaypopDriveFile>; upload(file: Blob, opts?: { name?: string }): Promise<MaypopDriveFile>; url(cid: string): Promise<string>; imageUrl(cid: string): Promise<string>; delete(cid: string): Promise<void>; remove(name: string): Promise<void>;}A photo wall
Section titled “A photo wall”await maypop.ready();
input.onchange = async () => { const file = await maypop.drive.upload(input.files![0]); // Keep the file's cid in KV, not a URL: URLs expire. await maypop.kv.set(`photo/${file.id}`, { cid: file.cid, name: file.name });};
maypop.kv.subscribe("photo/", async (entries) => { for (const { value } of entries) { const { cid } = value as { cid: string }; addImage(await maypop.drive.imageUrl(cid)); }});How it behaves
Section titled “How it behaves”- Names don’t overwrite.
writeto a name that exists fails withmaypop/conflict. Write a new name, orremovethe old file first. cididentifies the content. Store it in KV to refer to a file.url(cid)is short-lived. Fetch a fresh one when you need it; never save it.imageUrl(cid)is cached for fast display in this page only.delete(cid)removes one file;remove(name)removes every file with that name.- Names are
/-separated paths such asavatars/alice.png: up to 512 bytes, no empty,.or..segments, no backslashes. - Uploads are limited to
maxUploadBytes(50 MiB); a bigger file fails withmaypop/file-too-largebefore anything is sent. - Readers can list and download; writing needs edit or use access.
File policy
Section titled “File policy”By default, everyone with access can list and download every file, writers
can add files, and only the person who uploaded a file can delete it. Add
.maypop/drive-policy.json to your app’s source to change that; it takes
effect with the next published version.
It uses the same presets, roles and actions as the
KV policy, with a name pattern instead of a
key, and two extra conditions on uploads:
contentTypes: exact types such asimage/png(no wildcards).maxBytes: a size limit, at most 50 MiB.
Each person manages their own avatar; everyone can see all avatars:
{ "schemaVersion": 1, "mode": "advanced", "rules": [ { "actions": ["read", "create", "delete"], "roles": ["user", "admin", "owner"], "name": "avatars/{memberId}/**", "owner": null, "contentTypes": ["image/png", "image/jpeg", "image/webp"], "maxBytes": 5242880 }, { "actions": ["read"], "roles": ["guest", "user", "admin", "owner"], "name": "avatars/**", "owner": null } ]}Files a person can’t read are left out of their list. A policy can narrow
what someone’s role allows, never widen it: a reader can’t be given write
access. In Drive policies owner can only be { "source": "entryAuthor" },
the uploader.