Files
cursor_gen/flutter-cursor-templates/templates/rules/backend/supabase.mdc.tmpl
T

53 lines
1.4 KiB
Cheetah

---
description: "Supabase conventions for {{PROJECT_NAME}}"
alwaysApply: true
---
# Supabase Standards — {{PROJECT_NAME}}
## Row Level Security (RLS) awareness
- **ALWAYS** assume RLS is enabled — never write queries that assume full table access
- Test queries in the Supabase dashboard before implementing in Flutter
- If a query returns empty unexpectedly, check RLS policies first
## Queries
```dart
// ✅ Type-safe query with error handling
Future<List<Product>> getProducts() async {
final response = await _supabase
.from('products')
.select('id, name, price, category_id, categories(name)')
.eq('is_active', true)
.order('created_at', ascending: false)
.limit(50);
return response.map(Product.fromMap).toList();
}
```
## Realtime subscriptions
```dart
StreamSubscription<List<Map<String, dynamic>>>? _sub;
void watchOrders(String userId) {
_sub = _supabase
.from('orders')
.stream(primaryKey: ['id'])
.eq('user_id', userId)
.listen(
(data) => _updateOrders(data),
onError: (e) => _handleError(e),
);
}
@override
void dispose() {
_sub?.cancel(); // ALWAYS cancel in dispose()
super.dispose();
}
```
## Auth session
- Use `supabase.auth.onAuthStateChange` stream — never poll auth state
- Persist session: `supabase-flutter` handles this automatically via secure storage
- `session.accessToken` expires — check `session.isExpired` before sensitive operations