Initial commit from template
This commit is contained in:
142
.claude/skills/supabase-storage/SKILL.md
Normal file
142
.claude/skills/supabase-storage/SKILL.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
name: supabase-storage
|
||||
description: Supabase Storage fuer Datei-Upload und Download. Nutze diesen Skill fuer Bucket-Erstellung, File Upload, Download, Signed URLs und Storage Policies. Aktiviert bei Begriffen wie "Upload", "Download", "Datei", "File", "Bild hochladen", "Storage", "Bucket", "S3", "Bilder", "Avatar", "Dokumente".
|
||||
---
|
||||
|
||||
# Supabase Storage Skill
|
||||
|
||||
Dieser Skill hilft bei allen Storage-Operationen mit Supabase.
|
||||
|
||||
## Bucket erstellen
|
||||
|
||||
```typescript
|
||||
// Server-side mit Admin Client
|
||||
const { data, error } = await supabaseAdmin.storage.createBucket('avatars', {
|
||||
public: true,
|
||||
fileSizeLimit: 1024 * 1024 * 2, // 2MB
|
||||
allowedMimeTypes: ['image/png', 'image/jpeg', 'image/webp']
|
||||
});
|
||||
```
|
||||
|
||||
Oder via SQL:
|
||||
```sql
|
||||
INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
||||
VALUES (
|
||||
'avatars',
|
||||
'avatars',
|
||||
true,
|
||||
2097152,
|
||||
ARRAY['image/png', 'image/jpeg', 'image/webp']
|
||||
);
|
||||
```
|
||||
|
||||
## File Upload
|
||||
|
||||
```typescript
|
||||
async function uploadFile(file: File, bucket: string, path: string) {
|
||||
const { data, error } = await supabase.storage
|
||||
.from(bucket)
|
||||
.upload(path, file, {
|
||||
cacheControl: '3600',
|
||||
upsert: false // true = ueberschreiben erlaubt
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
// Public URL holen
|
||||
const { data: urlData } = supabase.storage
|
||||
.from(bucket)
|
||||
.getPublicUrl(path);
|
||||
|
||||
return urlData.publicUrl;
|
||||
}
|
||||
```
|
||||
|
||||
## File Download
|
||||
|
||||
```typescript
|
||||
// Als Blob
|
||||
const { data, error } = await supabase.storage
|
||||
.from('documents')
|
||||
.download('path/to/file.pdf');
|
||||
|
||||
// Public URL (oeffentliche Buckets)
|
||||
const { data } = supabase.storage
|
||||
.from('avatars')
|
||||
.getPublicUrl('user123/avatar.jpg');
|
||||
|
||||
// Signed URL (private Buckets, zeitlich begrenzt)
|
||||
const { data, error } = await supabase.storage
|
||||
.from('private-docs')
|
||||
.createSignedUrl('secret.pdf', 3600); // 1 Stunde
|
||||
```
|
||||
|
||||
## File Management
|
||||
|
||||
```typescript
|
||||
// Liste Dateien
|
||||
const { data, error } = await supabase.storage
|
||||
.from('bucket')
|
||||
.list('folder/', {
|
||||
limit: 100,
|
||||
sortBy: { column: 'created_at', order: 'desc' }
|
||||
});
|
||||
|
||||
// Loeschen
|
||||
const { error } = await supabase.storage
|
||||
.from('bucket')
|
||||
.remove(['path/file1.jpg', 'path/file2.jpg']);
|
||||
|
||||
// Verschieben
|
||||
const { error } = await supabase.storage
|
||||
.from('bucket')
|
||||
.move('old/path.jpg', 'new/path.jpg');
|
||||
```
|
||||
|
||||
## Storage Policies (RLS)
|
||||
|
||||
```sql
|
||||
-- User koennen eigene Dateien hochladen
|
||||
CREATE POLICY "Users 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 koennen eigene Dateien lesen
|
||||
CREATE POLICY "Users read own files"
|
||||
ON storage.objects FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
bucket_id = 'user-files' AND
|
||||
(storage.foldername(name))[1] = auth.uid()::text
|
||||
);
|
||||
|
||||
-- User koennen eigene Dateien loeschen
|
||||
CREATE POLICY "Users delete own files"
|
||||
ON storage.objects FOR DELETE
|
||||
TO authenticated
|
||||
USING (
|
||||
bucket_id = 'user-files' AND
|
||||
(storage.foldername(name))[1] = auth.uid()::text
|
||||
);
|
||||
|
||||
-- Oeffentlicher Lesezugriff
|
||||
CREATE POLICY "Public read"
|
||||
ON storage.objects FOR SELECT
|
||||
USING (bucket_id = 'public-assets');
|
||||
```
|
||||
|
||||
## React Upload Component
|
||||
|
||||
Siehe `templates/FileUpload.tsx` fuer eine fertige Component.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Ordnerstruktur: `{user_id}/{type}/{filename}`
|
||||
2. File Size Limits setzen
|
||||
3. MIME Types einschraenken
|
||||
4. Signed URLs fuer private Dateien
|
||||
5. Unique Filenames (z.B. mit Timestamp)
|
||||
Reference in New Issue
Block a user