๐Ÿš€ Supabase Annotations

pub package License: MIT GitHub stars

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

๐Ÿ—๏ธ 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:

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:

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

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

# Generate SQL schema files
dart run build_runner build

# Watch for changes and regenerate
dart run build_runner watch

5๏ธโƒฃ Generated Output

-- ๐Ÿ“„ 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:

@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:

@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:

@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:

// ๐Ÿ“Š 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:

@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:

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:

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:

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

ColumnType.text                    // TEXT
ColumnType.varchar(255)            // VARCHAR(255)
ColumnType.char(10)               // CHAR(10)

๐Ÿ”ข Numeric Types

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

ColumnType.timestamp              // TIMESTAMP
ColumnType.timestampWithTimeZone  // TIMESTAMPTZ
ColumnType.date                   // DATE
ColumnType.time                   // TIME
ColumnType.interval              // INTERVAL

๐ŸŽฏ Special Types

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

// ๐Ÿ“„ 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

@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

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

@RLSPolicy(
  name: 'users_own_data',
  type: RLSPolicyType.all,
  condition: 'auth.uid() = user_id',
)

๐Ÿข Multi-tenant Isolation

@RLSPolicy(
  name: 'tenant_isolation',
  type: RLSPolicyType.all,
  condition: 'tenant_id = auth.jwt() ->> "tenant_id"',
)

๐Ÿ‘ฅ Role-based Access

@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

@RLSPolicy(
  name: 'active_records_only',
  type: RLSPolicyType.select,
  condition: 'expires_at > NOW() AND is_active = true',
)

โšก Performance & Indexing

๐Ÿ” Index Types

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

@DatabaseIndex(type: IndexType.btree)
@DatabaseColumn(type: ColumnType.text)
late String status;

๐Ÿ“ˆ Composite Index

@DatabaseIndex(
  name: 'user_activity_idx',
  columns: ['user_id', 'created_at', 'activity_type'],
  type: IndexType.btree,
)

๐ŸŽฏ Partial Index

@DatabaseIndex(
  name: 'active_users_idx',
  columns: ['email'],
  where: "status = 'active' AND deleted_at IS NULL",
)

๐Ÿ” Expression Index

@DatabaseIndex(
  name: 'user_search_idx',
  expression: "to_tsvector('english', name || ' ' || email)",
  type: IndexType.gin,
)

๐Ÿ“ฑ JSON Index

@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

// Add this field to existing User class
@DatabaseColumn(
  type: ColumnType.integer,
  defaultValue: DefaultValue.zero,
)
int? age;

Generated Migration:

-- ๐Ÿ”„ 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

// Add relationship to existing table
@ForeignKey(
  table: 'companies',
  column: 'id',
  onDelete: ForeignKeyAction.setNull,
)
@DatabaseColumn(type: ColumnType.uuid)
String? companyId;

Generated Migration:

-- ๐Ÿ”— 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

# ๐ŸŽฏ 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

@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<String, dynamic>? metadata;

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

๐Ÿ›’ E-commerce System

@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<Map<String, dynamic>>? items;

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

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

๐Ÿ“Š Analytics & Logging

@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<String, dynamic>? 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

# 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

# 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
  • Include a minimal reproduction case
  • Provide environment details (Dart version, OS, etc.)

๐Ÿ’ก Feature Requests

  • Check existing 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

๐Ÿ’ฌ Community

๐Ÿ†˜ Need Help?


๐Ÿ“„ License

This project is licensed under the MIT License - see the 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 โ€ข ๐Ÿ“š Docs โ€ข ๐Ÿ’ฌ Community

Libraries

builder
Builder configuration for the Supabase schema generator.
supabase_annotations
A comprehensive code generator for creating Supabase/PostgreSQL database schemas from Dart model classes.