Storage

Bueno's storage module wraps Bun.s3 — Bun's native S3 client — for file uploads, downloads, and management across any S3-compatible service.

Setup

import { createStorage } from '@buenojs/bueno';

const storage = createStorage({
  bucket: 'my-uploads',
  region: 'us-east-1',
  credentials: {
    accessKeyId: Bun.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: Bun.env.AWS_SECRET_ACCESS_KEY!,
  },
  // For Cloudflare R2, Backblaze B2, MinIO, etc.:
  endpoint: Bun.env.S3_ENDPOINT,
});

Uploading files

// Upload from buffer
await storage.put('images/avatar.png', imageBuffer, {
  contentType: 'image/png',
  metadata: { userId: '42' },
});

// Upload from a web Request
app.post('/upload', async (ctx) => {
  const form = await ctx.formData();
  const file = form.get('file') as File;
  const buffer = await file.arrayBuffer();

  const key = `uploads/${Date.now()}-${file.name}`;
  await storage.put(key, buffer, { contentType: file.type });

  return ctx.json({ url: storage.publicUrl(key) });
});

Downloading files

// Get file as Blob
const blob = await storage.get('images/avatar.png');

// Get file as ArrayBuffer
const buffer = await storage.getBuffer('images/avatar.png');

// Get file as text
const text = await storage.getText('configs/settings.json');

// Stream response directly
app.get('/files/:key', async (ctx) => {
  const stream = await storage.getStream(ctx.params.key);
  if (!stream) return ctx.notFound();
  return new Response(stream);
});

Listing files

const files = await storage.list('uploads/');
// [{ key: 'uploads/photo.jpg', size: 12345, lastModified: Date }]

const all = await storage.list();

Deleting files

await storage.delete('uploads/old-photo.jpg');

// Delete multiple
await storage.deleteMany(['uploads/a.jpg', 'uploads/b.jpg']);

Presigned URLs

Generate temporary signed URLs for direct browser uploads or downloads:
// Upload URL (client uploads directly to S3)
const uploadUrl = await storage.presignUpload('uploads/photo.jpg', {
  expiresIn: 300,  // 5 minutes
  contentType: 'image/jpeg',
  maxSize: 5 * 1024 * 1024,  // 5MB
});

// Download URL
const downloadUrl = await storage.presignDownload('uploads/photo.jpg', {
  expiresIn: 3600,  // 1 hour
});

Public URLs

const url = storage.publicUrl('images/logo.png');
// "https://my-uploads.s3.amazonaws.com/images/logo.png"

Compatible services

Service Notes
AWS S3 Default, no extra config
Cloudflare R2 Set endpoint to your R2 URL
Backblaze B2 Set endpoint to B2 API URL
MinIO Self-hosted, set endpoint to MinIO URL
DigitalOcean Spaces S3-compatible

Released under the MIT License. Built with love by the Bueno Community.