Files
lumina-nextjs-template/.claude/commands/supabase-storage.md
2025-12-23 04:19:57 +01:00

200 lines
4.8 KiB
Markdown

# Supabase Storage Assistent
Du bist ein Experte für Supabase Storage. Hilf dem Benutzer bei File-Upload, Download und Bucket-Management.
## Deine Aufgaben
### 1. Bucket erstellen
```sql
-- Via SQL (Supabase Dashboard)
INSERT INTO storage.buckets (id, name, public)
VALUES ('avatars', 'avatars', true);
-- Oder via CLI
```
```typescript
// Via JavaScript (Admin/Service Role)
const { data, error } = await supabaseAdmin.storage.createBucket('avatars', {
public: true,
fileSizeLimit: 1024 * 1024 * 2, // 2MB
allowedMimeTypes: ['image/png', 'image/jpeg', 'image/webp']
});
```
### 2. File Upload
```typescript
// Client-side Upload
async function uploadFile(file: File, bucket: string, path: string) {
const { data, error } = await supabase.storage
.from(bucket)
.upload(path, file, {
cacheControl: '3600',
upsert: false
});
if (error) throw error;
return data;
}
// Mit Progress
async function uploadWithProgress(file: File, bucket: string, path: string) {
const { data, error } = await supabase.storage
.from(bucket)
.upload(path, file, {
onUploadProgress: (progress) => {
const percent = (progress.loaded / progress.total) * 100;
console.log(`Upload: ${percent.toFixed(0)}%`);
}
});
return { data, error };
}
```
### 3. File Download
```typescript
// Download als Blob
const { data, error } = await supabase.storage
.from('bucket')
.download('path/to/file.pdf');
// Public URL (für öffentliche Buckets)
const { data } = supabase.storage
.from('bucket')
.getPublicUrl('path/to/file.jpg');
// Signed URL (für private Buckets)
const { data, error } = await supabase.storage
.from('bucket')
.createSignedUrl('path/to/file.pdf', 3600); // 1 Stunde gültig
```
### 4. File Management
```typescript
// Liste Dateien
const { data, error } = await supabase.storage
.from('bucket')
.list('folder/', {
limit: 100,
offset: 0,
sortBy: { column: 'name', order: 'asc' }
});
// Datei löschen
const { error } = await supabase.storage
.from('bucket')
.remove(['path/to/file1.jpg', 'path/to/file2.jpg']);
// Datei verschieben/umbenennen
const { error } = await supabase.storage
.from('bucket')
.move('old/path.jpg', 'new/path.jpg');
// Datei kopieren
const { error } = await supabase.storage
.from('bucket')
.copy('source/path.jpg', 'dest/path.jpg');
```
### 5. Storage Policies (RLS)
```sql
-- Öffentlicher Lesezugriff
CREATE POLICY "Public read access"
ON storage.objects FOR SELECT
USING (bucket_id = 'public-bucket');
-- Authentifizierte User können eigene Dateien hochladen
CREATE POLICY "Users can upload own files"
ON storage.objects FOR INSERT
TO authenticated
WITH CHECK (
bucket_id = 'user-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);
-- User können nur eigene Dateien löschen
CREATE POLICY "Users can delete own files"
ON storage.objects FOR DELETE
TO authenticated
USING (
bucket_id = 'user-files' AND
(storage.foldername(name))[1] = auth.uid()::text
);
```
## React Upload Component
```typescript
'use client';
import { useState } from 'react';
import { supabase } from '@/lib/supabase';
interface FileUploadProps {
bucket: string;
onUpload: (url: string) => void;
}
export function FileUpload({ bucket, onUpload }: FileUploadProps) {
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState(0);
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
setUploading(true);
const fileExt = file.name.split('.').pop();
const fileName = `${Date.now()}.${fileExt}`;
const filePath = `uploads/${fileName}`;
const { error } = await supabase.storage
.from(bucket)
.upload(filePath, file);
if (error) {
console.error('Upload error:', error);
} else {
const { data } = supabase.storage.from(bucket).getPublicUrl(filePath);
onUpload(data.publicUrl);
}
setUploading(false);
};
return (
<div>
<input
type="file"
onChange={handleUpload}
disabled={uploading}
/>
{uploading && <span>Uploading...</span>}
</div>
);
}
```
## Best Practices
1. **Bucket-Struktur planen** - z.B. `{user_id}/{type}/{filename}`
2. **File Size Limits setzen** - Verhindert Missbrauch
3. **MIME Types einschränken** - Nur erlaubte Dateitypen
4. **Signed URLs für private Dateien** - Zeitlich begrenzt
5. **CDN nutzen** - Public URLs werden automatisch gecacht
---
Frage den Benutzer: Was möchtest du mit Supabase Storage machen?
- Neuen Bucket erstellen
- Upload Component bauen
- Download implementieren
- Storage Policies einrichten
- Dateien verwalten