An open API service indexing awesome lists of open source software.

https://github.com/ahmtydn/supabase_annotations

A code generator for creating Supabase/PostgreSQL database schemas from Dart model classes. Supports RLS policies, indexes, foreign keys, and schema validation.
https://github.com/ahmtydn/supabase_annotations

code-gen dart-package flutter-package generator postgres pub-dev schema-generator sql-generator

Last synced: 4 months ago
JSON representation

A code generator for creating Supabase/PostgreSQL database schemas from Dart model classes. Supports RLS policies, indexes, foreign keys, and schema validation.

Awesome Lists containing this project

README

          

# ๐Ÿš€ Supabase Annotations

[![pub package](https://img.shields.io/pub/v/supabase_annotations.svg)](https://pub.dev/packages/supabase_annotations)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![GitHub stars](https://img.shields.io/github/stars/ahmtydn/supabase_annotations.svg?style=social&label=Star)](https://github.com/ahmtydn/supabase_annotations)

A powerful, type-safe code generator for creating **Supabase/PostgreSQL** database schemas from Dart model classes. Build production-ready database schemas with **Row Level Security (RLS)**, **indexes**, **foreign keys**, **migrations**, and **table partitioning** - all from your Dart code.

---

## ๐Ÿ“š Table of Contents

- [โœจ Features](#-features)
- [๐Ÿš€ Quick Start](#-quick-start)
- [๐Ÿ“– Core Annotations](#-core-annotations)
- [๐Ÿ”ง Configuration](#-configuration)
- [๐Ÿ—„๏ธ Column Types & Constraints](#๏ธ-column-types--constraints)
- [๐Ÿ” Security & RLS Policies](#-security--rls-policies)
- [โšก Performance & Indexing](#-performance--indexing)
- [๐Ÿ”„ Migration Support](#-migration-support)
- [๐ŸŽฏ Advanced Examples](#-advanced-examples)
- [๐Ÿ“ Best Practices](#-best-practices)
- [๐Ÿ› ๏ธ Development](#๏ธ-development)
- [๐Ÿค Contributing](#-contributing)
- [๐Ÿ“„ License](#-license)

---

## โœจ Features

### ๐Ÿ—๏ธ **Schema Generation**
- **Type-Safe SQL Generation** - Convert Dart classes to PostgreSQL schemas
- **Full PostgreSQL Support** - All column types, constraints, and features
- **Automatic Documentation** - Generate SQL comments from Dart documentation

### ๐Ÿ” **Security First**
- **Row Level Security (RLS)** - Declarative RLS policy generation
- **Fine-Grained Permissions** - Control access at the row and column level
- **Authentication Integration** - Built-in Supabase auth helpers

### โšก **Performance Optimization**
- **Smart Indexing** - Automatic and custom index generation
- **Query Optimization** - Composite indexes and partial indexes
- **Table Partitioning** - Range and hash partitioning support

### ๐Ÿ”„ **Migration & Evolution**
- **Safe Schema Evolution** - Multiple migration strategies
- **Zero-Downtime Updates** - ADD COLUMN and ALTER TABLE support
- **Rollback Support** - Safe migration with fallback options

### ๐ŸŽฏ **Developer Experience**
- **IDE Integration** - Full IntelliSense and code completion
- **Comprehensive Validation** - Catch errors at build time
- **Rich Documentation** - Inline help and examples

---

## ๐Ÿš€ Quick Start

### 1๏ธโƒฃ Installation

Add to your `pubspec.yaml`:

```yaml
dependencies:
supabase_annotations: ^1.1.1

dev_dependencies:
build_runner: ^2.4.8
source_gen: ^1.5.0
```

### 2๏ธโƒฃ Configuration

Create `build.yaml` in your project root:

```yaml
targets:
$default:
builders:
supabase_annotations|schema_builder:
enabled: true
generate_for:
include:
- lib/**.dart
- example/**.dart
exclude:
- lib/**.g.dart
- lib/**.schema.dart
options:
# ๐Ÿ”„ Migration Strategy
migration_mode: 'createOrAlter' # Safe schema evolution
enable_column_adding: true # Add missing columns
generate_do_blocks: true # PostgreSQL DO blocks

# ๐Ÿ” Security Configuration
enable_rls_by_default: false # RLS on all tables

# ๐Ÿ“ Code Generation
generate_comments: true # Include documentation
validate_schema: true # Schema validation
format_sql: true # Format output
```

### 3๏ธโƒฃ Define Your Model

```dart
import 'package:supabase_annotations/supabase_annotations.dart';

@DatabaseTable(
name: 'users',
enableRLS: true,
comment: 'Application users with authentication',
)
@RLSPolicy(
name: 'users_own_data',
type: RLSPolicyType.all,
condition: 'auth.uid() = id',
)
@DatabaseIndex(
name: 'users_email_idx',
columns: ['email'],
isUnique: true,
)
class User {
@DatabaseColumn(
type: ColumnType.uuid,
isPrimaryKey: true,
defaultValue: DefaultValue.generateUuid,
)
String? id;

@DatabaseColumn(
type: ColumnType.text,
isUnique: true,
isNullable: false,
)
late String email;

@DatabaseColumn(
type: ColumnType.varchar(100),
isNullable: false,
)
late String fullName;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
)
late DateTime createdAt;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
)
late DateTime updatedAt;
}
```

### 4๏ธโƒฃ Generate Schema

```bash
# Generate SQL schema files
dart run build_runner build

# Watch for changes and regenerate
dart run build_runner watch
```

### 5๏ธโƒฃ Generated Output

```sql
-- ๐Ÿ“„ Generated: lib/models/user.schema.sql

-- ๐Ÿ—๏ธ Create table with RLS enabled
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
full_name VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

-- ๐Ÿ” Enable Row Level Security
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- ๐Ÿ›ก๏ธ Create RLS policy
CREATE POLICY users_own_data ON users
FOR ALL
USING (auth.uid() = id);

-- โšก Create performance indexes
CREATE UNIQUE INDEX users_email_idx ON users(email);

-- ๐Ÿ“ Add table comment
COMMENT ON TABLE users IS 'Application users with authentication';
```

---

## ๐Ÿ“– Core Annotations

### ๐Ÿ—๏ธ `@DatabaseTable`

Configure table-level settings:

```dart
@DatabaseTable(
name: 'custom_table_name', // ๐Ÿ“ Custom table name (optional)
enableRLS: true, // ๐Ÿ” Row Level Security
comment: 'Table description', // ๐Ÿ“„ Documentation
partitionBy: RangePartition( // ๐Ÿ“Š Table partitioning
columns: ['created_at']
),
)
class MyTable { }
```

### ๐Ÿท๏ธ `@DatabaseColumn`

Define column properties:

```dart
@DatabaseColumn(
name: 'custom_column_name', // ๐Ÿ“ Custom column name
type: ColumnType.varchar(255), // ๐ŸŽฏ PostgreSQL type
isNullable: false, // โŒ NOT NULL constraint
isPrimaryKey: true, // ๐Ÿ”‘ Primary key
isUnique: true, // โญ Unique constraint
defaultValue: DefaultValue.currentTimestamp, // ๐Ÿ”„ Default value
comment: 'Column description', // ๐Ÿ“„ Documentation
checkConstraints: ['value > 0'], // โœ… CHECK constraints
)
late String myField;
```

### ๐Ÿ”— `@ForeignKey`

Define relationships:

```dart
@ForeignKey(
table: 'users', // ๐ŸŽฏ Referenced table
column: 'id', // ๐Ÿ”— Referenced column
onDelete: ForeignKeyAction.cascade, // ๐Ÿ—‘๏ธ Delete behavior
onUpdate: ForeignKeyAction.restrict, // ๐Ÿ”„ Update behavior
)
@DatabaseColumn(type: ColumnType.uuid)
late String userId;
```

### โšก `@DatabaseIndex`

Optimize performance:

```dart
// ๐Ÿ“Š Composite index on table
@DatabaseIndex(
name: 'user_status_created_idx',
columns: ['status', 'created_at'],
type: IndexType.btree,
isUnique: false,
where: "status != 'deleted'", // ๐ŸŽฏ Partial index
)
class User { }

// ๐Ÿ” Single column index
@DatabaseIndex(type: IndexType.hash)
@DatabaseColumn(type: ColumnType.text)
late String status;
```

### ๐Ÿ›ก๏ธ `@RLSPolicy`

Secure your data:

```dart
@RLSPolicy(
name: 'user_read_own', // ๐Ÿ“ Policy name
type: RLSPolicyType.select, // ๐ŸŽฏ Operation type
condition: 'auth.uid() = user_id', // ๐Ÿ” Access condition
roles: ['authenticated'], // ๐Ÿ‘ฅ Database roles
comment: 'Users can read their own data', // ๐Ÿ“„ Documentation
)
class UserData { }
```

---

## ๐Ÿ”ง Configuration

### ๐Ÿ“‹ Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `migration_mode` | string | `'createOnly'` | Migration strategy |
| `enable_column_adding` | bool | `true` | Add missing columns |
| `generate_do_blocks` | bool | `true` | Use DO blocks for safety |
| `enable_rls_by_default` | bool | `false` | RLS on all tables |
| `add_timestamps` | bool | `false` | Auto-add timestamps |
| `use_explicit_nullability` | bool | `false` | Explicit NULL/NOT NULL |
| `generate_comments` | bool | `true` | Include documentation |
| `validate_schema` | bool | `true` | Schema validation |
| `format_sql` | bool | `true` | Format SQL output |

### ๐ŸŽฏ Environment-Specific Configurations

**๐Ÿ”ง Development Setup:**
```yaml
options:
migration_mode: 'createOrAlter' # Safe evolution
enable_rls_by_default: false # Easier testing
generate_comments: true # Full docs
validate_schema: true # Catch errors
format_sql: true # Readable output
```

**๐Ÿš€ Production Setup:**
```yaml
options:
migration_mode: 'createOrAlter' # Safe migrations
enable_column_adding: true # Allow evolution
generate_do_blocks: true # Extra safety
validate_schema: true # Strict validation
format_sql: true # Clean output
```

**๐Ÿค– CI/CD Pipeline:**
```yaml
options:
migration_mode: 'createOnly' # Standard creation
validate_schema: true # Fail on errors
generate_comments: false # Minimal output
format_sql: true # Consistent format
```

---

## ๐Ÿ—„๏ธ Column Types & Constraints

### ๐Ÿ“Š PostgreSQL Column Types

#### ๐Ÿ“ Text Types
```dart
ColumnType.text // TEXT
ColumnType.varchar(255) // VARCHAR(255)
ColumnType.char(10) // CHAR(10)
```

#### ๐Ÿ”ข Numeric Types
```dart
ColumnType.integer // INTEGER
ColumnType.bigint // BIGINT
ColumnType.decimal(10, 2) // DECIMAL(10,2)
ColumnType.real // REAL
ColumnType.doublePrecision // DOUBLE PRECISION
ColumnType.serial // SERIAL
ColumnType.bigserial // BIGSERIAL
```

#### ๐Ÿ“… Date/Time Types
```dart
ColumnType.timestamp // TIMESTAMP
ColumnType.timestampWithTimeZone // TIMESTAMPTZ
ColumnType.date // DATE
ColumnType.time // TIME
ColumnType.interval // INTERVAL
```

#### ๐ŸŽฏ Special Types
```dart
ColumnType.uuid // UUID
ColumnType.boolean // BOOLEAN
ColumnType.json // JSON
ColumnType.jsonb // JSONB
ColumnType.bytea // BYTEA
ColumnType.inet // INET
ColumnType.macaddr // MACADDR
ColumnType.point // POINT
ColumnType.array(ColumnType.text) // TEXT[]
```

### ๐Ÿ”„ Default Values

```dart
// ๐Ÿ“„ Literal values
DefaultValue.none // NULL
DefaultValue.zero // 0
DefaultValue.one // 1
DefaultValue.emptyString // ''
DefaultValue.emptyArray // ARRAY[]
DefaultValue.emptyObject // '{}'

// โšก Functions
DefaultValue.currentTimestamp // CURRENT_TIMESTAMP
DefaultValue.currentDate // CURRENT_DATE
DefaultValue.generateUuid // gen_random_uuid()
DefaultValue.autoIncrement // nextval(sequence)

// ๐Ÿญ Factory methods
DefaultValue.string('value') // 'value'
DefaultValue.number(42) // 42
DefaultValue.boolean(true) // true
DefaultValue.expression('NOW()') // Custom expression
```

### โœ… Constraints

```dart
@DatabaseColumn(
// ๐Ÿ”‘ Primary key
isPrimaryKey: true,

// โญ Unique constraint
isUnique: true,

// โŒ NOT NULL constraint
isNullable: false,

// โœ… CHECK constraints
checkConstraints: [
'length(email) > 0',
'email ~* \'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\$\'',
],
)
late String email;
```

---

## ๐Ÿ” Security & RLS Policies

### ๐Ÿ›ก๏ธ RLS Policy Types

```dart
RLSPolicyType.all // ๐ŸŒŸ All operations (CRUD)
RLSPolicyType.select // ๐Ÿ‘๏ธ Read operations only
RLSPolicyType.insert // โž• Insert operations only
RLSPolicyType.update // โœ๏ธ Update operations only
RLSPolicyType.delete // ๐Ÿ—‘๏ธ Delete operations only
```

### ๐ŸŽฏ Common RLS Patterns

#### ๐Ÿ‘ค User Owns Data
```dart
@RLSPolicy(
name: 'users_own_data',
type: RLSPolicyType.all,
condition: 'auth.uid() = user_id',
)
```

#### ๐Ÿข Multi-tenant Isolation
```dart
@RLSPolicy(
name: 'tenant_isolation',
type: RLSPolicyType.all,
condition: 'tenant_id = auth.jwt() ->> "tenant_id"',
)
```

#### ๐Ÿ‘ฅ Role-based Access
```dart
@RLSPolicy(
name: 'admin_full_access',
type: RLSPolicyType.all,
condition: 'auth.jwt() ->> "role" = "admin"',
roles: ['authenticated'],
)

@RLSPolicy(
name: 'user_read_only',
type: RLSPolicyType.select,
condition: 'auth.jwt() ->> "role" = "user"',
roles: ['authenticated'],
)
```

#### ๐Ÿ•’ Time-based Access
```dart
@RLSPolicy(
name: 'active_records_only',
type: RLSPolicyType.select,
condition: 'expires_at > NOW() AND is_active = true',
)
```

---

## โšก Performance & Indexing

### ๐Ÿ” Index Types

```dart
IndexType.btree // ๐ŸŒณ B-tree (default, general purpose)
IndexType.hash // #๏ธโƒฃ Hash (equality only)
IndexType.gin // ๐Ÿ” GIN (JSON, arrays, full-text)
IndexType.gist // ๐ŸŽฏ GiST (geometric, full-text)
IndexType.spgist // ๐Ÿ“Š SP-GiST (space-partitioned)
IndexType.brin // ๐Ÿ“ˆ BRIN (large ordered tables)
```

### ๐Ÿ“Š Index Strategies

#### ๐Ÿ” Single Column Index
```dart
@DatabaseIndex(type: IndexType.btree)
@DatabaseColumn(type: ColumnType.text)
late String status;
```

#### ๐Ÿ“ˆ Composite Index
```dart
@DatabaseIndex(
name: 'user_activity_idx',
columns: ['user_id', 'created_at', 'activity_type'],
type: IndexType.btree,
)
```

#### ๐ŸŽฏ Partial Index
```dart
@DatabaseIndex(
name: 'active_users_idx',
columns: ['email'],
where: "status = 'active' AND deleted_at IS NULL",
)
```

#### ๐Ÿ” Expression Index
```dart
@DatabaseIndex(
name: 'user_search_idx',
expression: "to_tsvector('english', name || ' ' || email)",
type: IndexType.gin,
)
```

#### ๐Ÿ“ฑ JSON Index
```dart
@DatabaseIndex(
name: 'metadata_search_idx',
expression: "(metadata -> 'tags')",
type: IndexType.gin,
)
```

---

## ๐Ÿ”„ Migration Support

### ๐ŸŽฏ Migration Modes

| Mode | Description | Use Case |
|------|-------------|----------|
| `createOnly` | Standard CREATE TABLE | ๐Ÿ†• New projects |
| `createIfNotExists` | CREATE TABLE IF NOT EXISTS | ๐Ÿ”’ Safe creation |
| `createOrAlter` | CREATE + ALTER for new columns | ๐Ÿ”„ Schema evolution |
| `alterOnly` | Only ALTER TABLE statements | ๐Ÿ› ๏ธ Existing schemas |
| `dropAndRecreate` | DROP and CREATE | ๐Ÿงช Development only |

### ๐Ÿ“ Migration Examples

#### ๐Ÿ†• Adding New Column
```dart
// Add this field to existing User class
@DatabaseColumn(
type: ColumnType.integer,
defaultValue: DefaultValue.zero,
)
int? age;
```

**Generated Migration:**
```sql
-- ๐Ÿ”„ Safe column addition
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'users' AND column_name = 'age'
) THEN
ALTER TABLE users ADD COLUMN age INTEGER DEFAULT 0;
END IF;
END $$;
```

#### ๐Ÿ”— Adding Foreign Key
```dart
// Add relationship to existing table
@ForeignKey(
table: 'companies',
column: 'id',
onDelete: ForeignKeyAction.setNull,
)
@DatabaseColumn(type: ColumnType.uuid)
String? companyId;
```

**Generated Migration:**
```sql
-- ๐Ÿ”— Safe foreign key addition
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'users' AND column_name = 'company_id'
) THEN
ALTER TABLE users ADD COLUMN company_id UUID;
ALTER TABLE users ADD CONSTRAINT users_company_id_fkey
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE SET NULL;
END IF;
END $$;
```

### ๐Ÿ›ก๏ธ Safe Migration Practices

```yaml
# ๐ŸŽฏ Recommended production configuration
options:
migration_mode: 'createOrAlter' # Safe evolution
enable_column_adding: true # Allow new columns
generate_do_blocks: true # Extra safety checks
validate_schema: true # Comprehensive validation
```

---

## ๐ŸŽฏ Advanced Examples

### ๐Ÿข Multi-tenant SaaS Application

```dart
@DatabaseTable(
name: 'documents',
enableRLS: true,
comment: 'Multi-tenant document storage',
)
@RLSPolicy(
name: 'tenant_isolation',
type: RLSPolicyType.all,
condition: 'tenant_id = auth.jwt() ->> "tenant_id"',
)
@DatabaseIndex(
name: 'documents_tenant_created_idx',
columns: ['tenant_id', 'created_at'],
)
@DatabaseIndex(
name: 'documents_search_idx',
expression: "to_tsvector('english', title || ' ' || content)",
type: IndexType.gin,
)
class Document {
@DatabaseColumn(
type: ColumnType.uuid,
isPrimaryKey: true,
defaultValue: DefaultValue.generateUuid,
)
String? id;

@ForeignKey(
table: 'tenants',
column: 'id',
onDelete: ForeignKeyAction.cascade,
)
@DatabaseColumn(
type: ColumnType.uuid,
isNullable: false,
)
late String tenantId;

@DatabaseColumn(
type: ColumnType.text,
isNullable: false,
checkConstraints: ['length(title) > 0'],
)
late String title;

@DatabaseColumn(type: ColumnType.text)
String? content;

@DatabaseColumn(
type: ColumnType.jsonb,
defaultValue: DefaultValue.emptyObject,
)
Map? metadata;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
)
late DateTime createdAt;
}
```

### ๐Ÿ›’ E-commerce System

```dart
@DatabaseTable(
name: 'orders',
enableRLS: true,
comment: 'Customer orders with audit trail',
)
@RLSPolicy(
name: 'customers_own_orders',
type: RLSPolicyType.select,
condition: 'customer_id = auth.uid()',
)
@RLSPolicy(
name: 'staff_manage_orders',
type: RLSPolicyType.all,
condition: 'auth.jwt() ->> "role" IN ("admin", "staff")',
)
@DatabaseIndex(
name: 'orders_customer_status_idx',
columns: ['customer_id', 'status', 'created_at'],
)
@DatabaseIndex(
name: 'orders_total_idx',
columns: ['total_amount'],
where: "status != 'cancelled'",
)
class Order {
@DatabaseColumn(
type: ColumnType.uuid,
isPrimaryKey: true,
defaultValue: DefaultValue.generateUuid,
)
String? id;

@ForeignKey(
table: 'customers',
column: 'id',
onDelete: ForeignKeyAction.restrict,
)
@DatabaseColumn(
type: ColumnType.uuid,
isNullable: false,
)
late String customerId;

@DatabaseColumn(
type: ColumnType.varchar(20),
defaultValue: DefaultValue.string('pending'),
checkConstraints: [
"status IN ('pending', 'processing', 'shipped', 'delivered', 'cancelled')"
],
)
late String status;

@DatabaseColumn(
type: ColumnType.decimal(10, 2),
isNullable: false,
checkConstraints: ['total_amount >= 0'],
)
late double totalAmount;

@DatabaseColumn(
type: ColumnType.jsonb,
comment: 'Order line items with product details',
)
List>? items;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
)
late DateTime createdAt;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
)
late DateTime updatedAt;
}
```

### ๐Ÿ“Š Analytics & Logging

```dart
@DatabaseTable(
name: 'events',
comment: 'Application event tracking',
partitionBy: RangePartition(columns: ['created_at']),
)
@DatabaseIndex(
name: 'events_type_created_idx',
columns: ['event_type', 'created_at'],
)
@DatabaseIndex(
name: 'events_user_session_idx',
columns: ['user_id', 'session_id'],
where: "user_id IS NOT NULL",
)
@DatabaseIndex(
name: 'events_properties_idx',
expression: "(properties -> 'category')",
type: IndexType.gin,
)
class Event {
@DatabaseColumn(
type: ColumnType.uuid,
isPrimaryKey: true,
defaultValue: DefaultValue.generateUuid,
)
String? id;

@DatabaseColumn(
type: ColumnType.varchar(50),
isNullable: false,
)
late String eventType;

@DatabaseColumn(type: ColumnType.uuid)
String? userId;

@DatabaseColumn(type: ColumnType.uuid)
String? sessionId;

@DatabaseColumn(
type: ColumnType.jsonb,
defaultValue: DefaultValue.emptyObject,
)
Map? properties;

@DatabaseColumn(
type: ColumnType.inet,
comment: 'Client IP address',
)
String? ipAddress;

@DatabaseColumn(
type: ColumnType.text,
comment: 'User agent string',
)
String? userAgent;

@DatabaseColumn(
type: ColumnType.timestampWithTimeZone,
defaultValue: DefaultValue.currentTimestamp,
isNullable: false,
)
late DateTime createdAt;
}
```

---

## ๐Ÿ“ Best Practices

### ๐Ÿ—๏ธ Schema Design

#### โœ… **DO:**
- Use descriptive, meaningful names
- Follow PostgreSQL naming conventions (snake_case)
- Keep names under 63 characters
- Add comprehensive comments and documentation
- Use appropriate column types for your data

#### โŒ **DON'T:**
- Use reserved keywords as names
- Create overly complex nested structures
- Forget to add indexes on frequently queried columns
- Skip validation constraints

### ๐Ÿ” Security Guidelines

#### โœ… **DO:**
- Always enable RLS on tables with sensitive data
- Use specific, restrictive policy conditions
- Test policies thoroughly with different user roles
- Document security requirements and assumptions
- Use parameterized conditions to prevent injection

#### โŒ **DON'T:**
- Rely solely on application-level security
- Create overly permissive policies
- Forget to test edge cases in policy conditions
- Hardcode user IDs in policies

### โšก Performance Optimization

#### โœ… **DO:**
- Add indexes on frequently queried columns
- Use composite indexes for multi-column queries
- Consider partial indexes for filtered queries
- Use appropriate index types for your use case
- Monitor query performance regularly

#### โŒ **DON'T:**
- Create too many indexes (impacts write performance)
- Index every column "just in case"
- Forget to maintain statistics on large tables
- Ignore query execution plans

### ๐Ÿ”„ Migration Management

#### โœ… **DO:**
- Use migration modes for schema evolution
- Test migrations on staging data first
- Plan for rollback scenarios
- Document breaking changes thoroughly
- Use `createOrAlter` mode for production

#### โŒ **DON'T:**
- Drop tables or columns without backup
- Skip testing migrations
- Apply untested migrations to production
- Forget to version your schema changes

---

## ๐Ÿ› ๏ธ Development

### ๐Ÿš€ Getting Started

```bash
# Clone the repository
git clone https://github.com/ahmtydn/supabase_annotations.git
cd supabase_annotations

# Install dependencies
dart pub get

# Run tests
dart test

# Run analysis
dart analyze

# Generate documentation
dart doc
```

### ๐Ÿงช Running Examples

```bash
# Navigate to examples
cd example

# Generate schemas for all examples
dart run build_runner build

# View generated SQL files
ls lib/*.schema.sql
```

### ๐Ÿ” Project Structure

```
lib/
โ”œโ”€โ”€ builder.dart # Build configuration
โ”œโ”€โ”€ supabase_annotations.dart # Public API
โ””โ”€โ”€ src/
โ”œโ”€โ”€ annotations/ # Annotation definitions
โ”‚ โ”œโ”€โ”€ database_column.dart
โ”‚ โ”œโ”€โ”€ database_index.dart
โ”‚ โ”œโ”€โ”€ database_table.dart
โ”‚ โ”œโ”€โ”€ foreign_key.dart
โ”‚ โ””โ”€โ”€ rls_policy.dart
โ”œโ”€โ”€ generators/ # Code generation logic
โ”‚ โ””โ”€โ”€ schema_generator.dart
โ””โ”€โ”€ models/ # Data models
โ”œโ”€โ”€ column_types.dart
โ”œโ”€โ”€ default_values.dart
โ”œโ”€โ”€ foreign_key_actions.dart
โ”œโ”€โ”€ index_types.dart
โ”œโ”€โ”€ migration_config.dart
โ”œโ”€โ”€ partition_strategy.dart
โ”œโ”€โ”€ table_constraints.dart
โ””โ”€โ”€ validators.dart
```

---

## ๐Ÿค Contributing

We welcome contributions! Here's how you can help:

### ๐Ÿ› Bug Reports

- Use the [issue tracker](https://github.com/ahmtydn/supabase_annotations/issues)
- Include a minimal reproduction case
- Provide environment details (Dart version, OS, etc.)

### ๐Ÿ’ก Feature Requests

- Check existing [discussions](https://github.com/ahmtydn/supabase_annotations/discussions)
- Explain the use case and benefits
- Consider implementation complexity

### ๐Ÿ”ง Pull Requests

1. **Fork** the repository
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
3. **Add** tests for new functionality
4. **Ensure** all tests pass (`dart test`)
5. **Run** analysis (`dart analyze`)
6. **Commit** changes (`git commit -m 'Add amazing feature'`)
7. **Push** to branch (`git push origin feature/amazing-feature`)
8. **Submit** a pull request

### ๐Ÿ“‹ Development Guidelines

- Follow the existing code style
- Add comprehensive tests
- Update documentation
- Include examples for new features
- Ensure backward compatibility

---

## ๐Ÿ“ž Support & Community

### ๐Ÿ“š **Documentation**
- [API Reference](https://pub.dev/documentation/supabase_annotations/latest/)
- [Migration Guide](https://github.com/ahmtydn/supabase_annotations/blob/main/MIGRATION_GUIDE.md)
- [Examples](https://github.com/ahmtydn/supabase_annotations/tree/main/example)

### ๐Ÿ’ฌ **Community**
- [GitHub Discussions](https://github.com/ahmtydn/supabase_annotations/discussions)
- [Issue Tracker](https://github.com/ahmtydn/supabase_annotations/issues)

### ๐Ÿ†˜ **Need Help?**
- Check the [FAQ](https://github.com/ahmtydn/supabase_annotations/discussions/categories/q-a)
- Search existing [issues](https://github.com/ahmtydn/supabase_annotations/issues)
- Ask in [discussions](https://github.com/ahmtydn/supabase_annotations/discussions)

---

## ๐Ÿ“„ License

This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.

---

## ๐Ÿ™ Acknowledgments

- **Supabase Team** - For creating an amazing platform
- **Dart Team** - For excellent tooling and language features
- **PostgreSQL Community** - For the world's most advanced open source database
- **Contributors** - For making this project better

---

## ๐ŸŒŸ Show Your Support

If this project helped you, please consider:

- โญ **Star** the repository
- ๐Ÿ”— **Share** with your team
- ๐Ÿ› **Report** issues
- ๐Ÿ’ก **Suggest** improvements
- ๐Ÿค **Contribute** code

---

**Built with โค๏ธ for the Supabase and Dart communities**

[๐ŸŒ Website](https://github.com/ahmtydn/supabase_annotations) โ€ข [๐Ÿ“š Docs](https://pub.dev/packages/supabase_annotations) โ€ข [๐Ÿ’ฌ Community](https://github.com/ahmtydn/supabase_annotations/discussions)