plugins

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 9, 2026 License: MIT Imports: 9 Imported by: 0

README ΒΆ

pgsquash Plugin Architecture

Version: 0.9.7 Status: Production Ready βœ…

This directory contains the unified plugin system for third-party integrations (auth providers, ORMs, Platforms).


🎯 Quick Overview

The plugin system automatically detects and optimizes for popular frameworks:

  • Clerk - JWT v2 organization claims
  • Supabase - Auth schema, RLS policies, storage
  • Prisma - Migration metadata, shadow databases
  • Drizzle - IDENTITY columns, modern PostgreSQL patterns

Zero configuration required - plugins auto-detect from migration patterns.


πŸ“¦ Architecture Overview

Lifecycle Hooks

Plugins integrate into all migration phases:

  1. Detection - Pattern matching to identify applicable frameworks
  2. Enrichment - Add metadata to parsed statements
  3. Transformation - Pre-parse SQL modifications
  4. Consolidation - Custom squashing rules
  5. Validation - Compatibility layer injection
Priority System
90-100: Auth Services (Clerk: 95, Supabase: 90)
70-89:  ORMs (Prisma: 75, Drizzle: 75)
50-69:  Platforms (future: Neon, Railway)
0-49:   Utilities

Higher priority wins conflicts. Example:

Detected: Clerk (95) + Supabase (90)
Result: Clerk active, Supabase excluded
Auto-Discovery

No configuration required - plugins detect themselves:


# Prisma project

./pgsquash squash prisma/migrations/*/migration.sql

# [plugins] Detected: prisma

# Drizzle project

./pgsquash squash drizzle/*/migration.sql

# [plugins] Detected: drizzle

# Clerk + Prisma project

./pgsquash squash migrations/*.sql

# [plugins] Detected: clerk, prisma


πŸ”Œ Implemented Plugins

1. Clerk Plugin (clerk/)

Priority: 95 (Auth tier) Market Share: ~15% authentication Status: βœ… Production Ready

Detection Patterns
  • JWT v2 organization claims: auth.jwt()->'o'->>'id'
  • Clerk helper functions: clerk_user_id(), clerk_org_id()
  • Organization-scoped RLS policies
Features
-- Adds STABLE markers to auth functions
CREATE FUNCTION clerk_user_id() RETURNS TEXT
LANGUAGE plpgsql SECURITY DEFINER STABLE  -- ← Added by plugin
AS $$ BEGIN RETURN auth.jwt()->>'sub'; END; $$;

-- Injects compatibility layer for validation
CREATE FUNCTION auth.jwt() RETURNS JSONB STABLE AS $$
    SELECT '{"sub": "user_test", "o": {"id": "org_test"}}'::jsonb;
$$ LANGUAGE sql;
Consolidation Rules
  • Never consolidates auth helper functions
  • Preserves organization-scoped RLS policies
  • Protects JWT claim transformations

2. Supabase Plugin (supabase/)

Priority: 90 (Auth tier) Market Share: ~20% backend-as-a-service Status: βœ… Production Ready

Detection Patterns
  • auth.uid() function calls
  • auth.users, auth.schema references
  • Storage bucket policies: storage.buckets, storage.objects
  • Realtime subscriptions
Features
-- Adds STABLE markers
CREATE POLICY "user_policy" ON users
USING (auth.uid() = user_id);  -- STABLE marker added to auth.uid()

-- Injects Supabase compatibility layer
CREATE SCHEMA IF NOT EXISTS auth;
CREATE FUNCTION auth.uid() RETURNS UUID STABLE AS $$
    SELECT 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'::uuid;
$$ LANGUAGE sql;
Consolidation Rules
  • Preserves RLS policies (never consolidates)
  • Protects storage bucket configurations
  • Maintains realtime publication settings

3. Prisma Plugin (prisma/)

Priority: 75 (ORM tier) Market Share: ~60% TypeScript ORMs Status: βœ… Production Ready

Detection Patterns
  • _prisma_migrations table
  • Timestamp directory structure: YYYYMMDDHHMMSS_name/
  • Prisma comments: -- CreateTable, -- AlterTable
  • Auto-increment pattern: DEFAULT nextval('table_seq'::regclass)
  • VARCHAR(191) lengths (MySQL compatibility)
Features
-- Never consolidates migration metadata
CREATE TABLE "_prisma_migrations" (
  id VARCHAR(36) PRIMARY KEY,
  checksum VARCHAR(64) NOT NULL,
  migration_name VARCHAR(255) NOT NULL,
  ...
);  -- Always preserved

-- Enum protection (TypeScript mapping)
CREATE TYPE "Role" AS ENUM ('USER', 'ADMIN');
-- Never consolidated - breaks TypeScript types

-- Index optimization
-- Before: DROP + CREATE
-- After: Single CREATE (consolidated)
Transformations
  • VARCHAR(191) β†’ VARCHAR(255) for non-indexed columns
  • Function volatility markers (STABLE)
  • Shadow database pattern handling

4. Drizzle Plugin (drizzle/)

Priority: 75 (ORM tier) Market Share: ~25% TypeScript ORMs (growing) Status: βœ… Production Ready

Detection Patterns
  • __drizzle_migrations table
  • GENERATED ALWAYS AS IDENTITY columns
  • GENERATED BY DEFAULT AS IDENTITY columns
  • Drizzle directory: drizzle/TIMESTAMP_name/
  • snapshot.json files
Features
-- IDENTITY column support (PostgreSQL 14+ best practice)
CREATE TABLE "users" (
  "id" INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
  "email" TEXT UNIQUE NOT NULL
);

-- Generated columns preservation
CREATE TABLE "products" (
  "price" NUMERIC NOT NULL,
  "tax" NUMERIC GENERATED ALWAYS AS (price * 0.1) STORED
);

-- Sequence optimization
-- Removes redundant defaults (INCREMENT BY 1, START WITH 1)
Transformations
  • Sequence simplification (remove defaults)
  • Optional SERIAL β†’ IDENTITY conversion
  • Function volatility markers (IMMUTABLE for generated, VOLATILE for triggers)

πŸ—οΈ Directory Structure

internal/plugins/
β”œβ”€β”€ plugin.go             # Plugin interface (12 lifecycle hooks)

β”œβ”€β”€ registry.go           # Global registry with auto-discovery

β”œβ”€β”€ README.md             # This file

β”‚
β”œβ”€β”€ clerk/                # Clerk authentication

β”‚   β”œβ”€β”€ clerk.go          # Detection, enrichment, validation

β”‚   β”œβ”€β”€ consolidation.go  # Consolidation rules

β”‚   └── transformations.go # SQL transformations

β”‚
β”œβ”€β”€ supabase/             # Supabase Platform

β”‚   β”œβ”€β”€ supabase.go
β”‚   β”œβ”€β”€ consolidation.go
β”‚   └── transformations.go
β”‚
β”œβ”€β”€ prisma/               # Prisma ORM

β”‚   β”œβ”€β”€ prisma.go
β”‚   β”œβ”€β”€ consolidation.go
β”‚   └── transformations.go
β”‚
└── drizzle/              # Drizzle ORM

    β”œβ”€β”€ drizzle.go
    β”œβ”€β”€ consolidation.go
    └── transformations.go

πŸ”§ Configuration

Default (Auto-Detect)
{
  "plugins": {
    "auto_detect": true,
    "enabled_plugins": [],
    "disabled_plugins": [],
    "verbose": false
  }
}
Manual Control
{
  "plugins": {
    "auto_detect": false,
    "enabled_plugins": ["clerk", "prisma"],
    "disabled_plugins": ["supabase"],
    "verbose": true
  }
}
Plugin-Specific Configuration
{
  "third_party_integrations": {
    "clerk": {
      "jwt_version": "v2",
      "preserve_auth_helpers": true
    },
    "supabase": {
      "preserve_auth_schema": true,
      "preserve_storage_schema": true
    },
    "prisma": {
      "preserve_migration_table": true,
      "shadow_database": true,
      "optimize_indices": true
    },
    "drizzle": {
      "prefer_identity_columns": true,
      "preserve_drizzle_meta": true,
      "optimize_sequences": true
    }
  }
}

πŸš€ Usage

View Registered Plugins
./pgsquash --version

# [plugins] Registered plugin: clerk (priority: 95)

# [plugins] Registered plugin: supabase (priority: 90)

# [plugins] Registered plugin: prisma (priority: 75)

# [plugins] Registered plugin: drizzle (priority: 75)


# Plugins detect automatically

./pgsquash squash migrations/*.sql

# With verbose logging

./pgsquash squash migrations/*.sql --config pgsquash.config.json

# (set plugins.verbose: true in config)

Test Detection

# Create test migration with Prisma pattern

echo "CREATE TABLE _prisma_migrations (...)" > test.sql

./pgsquash analyze test.sql --verbose

# [plugins] Detected: prisma


πŸ’» Creating a Plugin

Step 1: Create Plugin Package
mkdir internal/plugins/myservice
Step 2: Implement Plugin Interface
// internal/plugins/myservice/myservice.go
package myservice

import (
    "context"
    "github.com/capysquash/pgsquash-engine/internal/plugins"
    "github.com/capysquash/pgsquash-engine/internal/types"
)

type MyServicePlugin struct {
    *plugins.BasePlugin
}

func NewMyServicePlugin() *MyServicePlugin {
    return &MyServicePlugin{
        BasePlugin: plugins.NewBasePlugin("myservice", 80),
    }
}

// Required: Detect if this plugin applies
func (p *MyServicePlugin) Detect(migrations []*types.Migration) bool {
    for _, migration := range migrations {
        for _, stmt := range migration.Statements {
            if strings.Contains(stmt.SQL, "my_pattern") {
                return true
            }
        }
    }
    return false
}

// Optional: Configure from pgsquash.config.json
func (p *MyServicePlugin) Initialize(ctx context.Context, config interface{}) error {
    return nil
}

// Optional: Enrich statements with metadata
func (p *MyServicePlugin) EnrichStatement(ctx context.Context, stmt *types.Statement) error {
    return nil
}

// Optional: Transform SQL before parsing
func (p *MyServicePlugin) TransformSQL(ctx context.Context, sql string) (string, error) {
    return sql, nil
}

// Optional: Add consolidation rules
func (p *MyServicePlugin) GetConsolidationRules() []interface{} {
    return nil
}

// Optional: Should preserve this statement?
func (p *MyServicePlugin) ShouldPreserve(stmt *types.Statement) bool {
    return false
}

// Optional: Inject compatibility SQL for validation
func (p *MyServicePlugin) GetCompatibilitySQL(ctx context.Context) ([]string, error) {
    return nil, nil
}

// Optional: Validate schema after migration
func (p *MyServicePlugin) ValidateSchema(ctx context.Context, db *sql.DB) error {
    return nil
}
Step 3: Register Plugin

Add the plugin to builtinPlugins() in pkg/plugins/detection.go. That list is the single source of truth for built-in plugins β€” plugins.RegisterDefault() registers from it, and the public detection/compatibility APIs derive from it:

// pkg/plugins/detection.go
import "github.com/capysquash/pgsquash-engine/internal/plugins/myservice"

func builtinPlugins() []internal_plugins.Plugin {
    return []internal_plugins.Plugin{
        clerk.NewClerkPlugin(),
        supabase.NewSupabasePlugin(),
        prisma.NewPrismaPlugin(),
        drizzle.NewDrizzlePlugin(),
        myservice.NewMyServicePlugin(), // ← Add here
    }
}
Step 4: Build & Test
go build -o pgsquash cmd/pgsquash/main.go
./pgsquash --version  # Should show your plugin

./pgsquash analyze test-migrations/*.sql --verbose

πŸ“Š Implementation Status

βœ… Completed (v0.9.7)
  • Core Infrastructure

  • Plugin interface (12 lifecycle hooks)

  • Global registry with auto-discovery

  • Priority-based conflict resolution

  • Lazy initialization

  • Shared types package (import cycle resolution)

  • Integration Points

  • Parser integration (statement enrichment)

  • Transformer integration (pre-parse transformations)

  • Validator integration (compatibility layers)

  • Squasher integration (consolidation rules)

  • Main registration

  • Auth Plugins (2/4)

  • Clerk (JWT v2, organization claims)

  • Supabase (auth.uid(), RLS, storage)

  • Auth0 (enterprise RBAC)

  • NextAuth (Next.js adapters)

  • ORM Plugins (2/3)

  • Prisma (migration metadata, enums)

  • Drizzle (IDENTITY columns, generated)

  • TypeORM (decorators, entities)

πŸ“‹ Planned (Future Phases)

Phase 4: Additional Auth (1-2 weeks)

  • Auth0 plugin
  • NextAuth plugin
  • Firebase Auth plugin

Phase 5: Platform Plugins (2-3 weeks)

  • Neon (serverless PostgreSQL)
  • Railway (multi-environment)
  • PlanetScale (MySQL compatibility)

Phase 6: Community (ongoing)

  • Plugin development guide
  • Community plugin template
  • Plugin marketplace
  • Version management

πŸŽ“ Technical Details

Import Cycle Resolution

Problem: parser ↔ plugins circular dependency

Solution: Shared types package

Before: parser β†’ plugins β†’ parser (CYCLE!)
After:  parser β†’ types ← plugins (NO CYCLE!)

Implementation: internal/types/parser_types.go

Type Aliases for Backward Compatibility
// internal/parser/parser.go
type Statement = types.Statement
type Migration = types.Migration

const (
    TypeTable = types.TypeTable
    OpCreate = types.OpCreate
)

All existing code continues to work without changes.

Pre-Parse Transformations

Plugins transform SQL before pg_query parsing:

// Step 0: Plugin transformations (regex-based)
transformedSQL, _ := applyPluginTransformations(ctx, sql)

// Step 1: Parse with pg_query
parseTree, _ := pg_query.Parse(transformedSQL)

This handles cases where pg_query would fail on plugin-specific syntax.


🀝 Contributing

Adding a New Plugin
  1. Create plugin package: internal/plugins/yourservice/
  2. Implement Plugin interface (or embed BasePlugin)
  3. Add consolidation rules in consolidation.go
  4. Add transformations in transformations.go
  5. Register in cmd/pgsquash/main.go
  6. Add tests (unit + integration)
  7. Update configuration example
  8. Document in this README
Testing Guidelines

Unit Tests:

func TestMyPluginDetection(t *testing.T) {
    plugin := myservice.NewMyServicePlugin()
    migrations := createTestMigrations("SELECT * FROM my_pattern;")
    assert.True(t, plugin.Detect(migrations))
}

Integration Tests:

func TestMyPluginWorkflow(t *testing.T) {
    // Test full detection β†’ transformation β†’ consolidation β†’ validation
}

πŸ“š Additional Resources

  • Architecture Deep-Dive: /docs/ARCHITECTURE.md
  • Configuration Reference: /docs/CONFIGURATION.md
  • Session Notes: /archive/session-notes/ (implementation history)

Last Updated: 2025-10-06. Version: 0.9.7. Plugins: 4 production-ready (Clerk, Supabase, Prisma, Drizzle).

Documentation ΒΆ

Overview ΒΆ

Package plugins provides a unified third-party integration system. It allows third-party services (auth providers, ORMs, managed Platforms) to hook into the migration analysis, transformation, and validation pipeline.

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func Register ΒΆ

func Register(plugin Plugin) error

Register adds a plugin to the global registry (convenience function)

Types ΒΆ

type BaseConsolidator ΒΆ

type BaseConsolidator struct {
	// contains filtered or unexported fields
}

BaseConsolidator provides common consolidation logic for plugins

func NewBaseConsolidator ΒΆ

func NewBaseConsolidator(name string) *BaseConsolidator

NewBaseConsolidator creates a new base consolidator

type BasePlugin ΒΆ

type BasePlugin struct {
	// contains filtered or unexported fields
}

BasePlugin provides default implementations for optional Plugin methods

func NewBasePlugin ΒΆ

func NewBasePlugin(name string, priority int) *BasePlugin

NewBasePlugin creates a base plugin with common defaults

func (*BasePlugin) DetectAuthPattern ΒΆ

func (bp *BasePlugin) DetectAuthPattern(stmt *types.Statement) string

func (*BasePlugin) DetectPatterns ΒΆ

func (bp *BasePlugin) DetectPatterns(sql string) []Pattern

func (*BasePlugin) EnrichStatement ΒΆ

func (bp *BasePlugin) EnrichStatement(ctx context.Context, stmt *types.Statement) error

Default implementations (no-ops)

func (*BasePlugin) FixFunctionVolatility ΒΆ

func (bp *BasePlugin) FixFunctionVolatility(ctx context.Context, functionSQL string) (string, error)

func (*BasePlugin) GetConflictingPlugins ΒΆ

func (bp *BasePlugin) GetConflictingPlugins() []string

func (*BasePlugin) GetConsolidationRules ΒΆ

func (bp *BasePlugin) GetConsolidationRules() []ConsolidationRule

func (*BasePlugin) GetRequiredExtensions ΒΆ

func (bp *BasePlugin) GetRequiredExtensions() []string

func (*BasePlugin) InjectCompatibilityLayer ΒΆ

func (bp *BasePlugin) InjectCompatibilityLayer(ctx context.Context) string

func (*BasePlugin) Name ΒΆ

func (bp *BasePlugin) Name() string

func (*BasePlugin) Priority ΒΆ

func (bp *BasePlugin) Priority() int

func (*BasePlugin) ShouldPreserve ΒΆ

func (bp *BasePlugin) ShouldPreserve(stmt *types.Statement) bool

func (*BasePlugin) TransformSQL ΒΆ

func (bp *BasePlugin) TransformSQL(ctx context.Context, sql string) (string, error)

func (*BasePlugin) ValidateSchema ΒΆ

func (bp *BasePlugin) ValidateSchema(ctx context.Context, db *sql.DB) error

type ConsolidationRule ΒΆ

type ConsolidationRule struct {
	Name        string                                    // Rule identifier
	Priority    int                                       // Higher priority overrides conflicts
	ObjectType  types.ObjectType                          // Target object type
	AuthPattern types.AuthPatternType                     // Target auth pattern (if applicable)
	Conflicts   []string                                  // Conflicting rule names
	CanMerge    func([]*types.Statement) bool             // Check if statements can merge
	Merge       func([]*types.Statement) *types.Statement // Perform merge
}

ConsolidationRule defines how to consolidate plugin-specific statements

type FunctionConsolidator ΒΆ

type FunctionConsolidator struct {
	*BaseConsolidator
}

FunctionConsolidator provides common function consolidation helpers

func NewFunctionConsolidator ΒΆ

func NewFunctionConsolidator(name string) *FunctionConsolidator

NewFunctionConsolidator creates a new function consolidator

func (*FunctionConsolidator) AllSameFunctionSignature ΒΆ

func (fc *FunctionConsolidator) AllSameFunctionSignature(statements []*types.Statement) bool

AllSameFunctionSignature checks if all functions have the same signature

type Location ΒΆ

type Location struct {
	StartLine   int
	StartColumn int
	EndLine     int
	EndColumn   int
}

Location represents a position in SQL source

type Pattern ΒΆ

type Pattern struct {
	Type     PatternType       // Pattern category
	Name     string            // Pattern identifier (e.g., "clerk_org_function", "prisma_directive")
	Location Location          // Source location in SQL
	Metadata map[string]string // Pattern-specific metadata
	Severity PatternSeverity   // How important is this pattern
}

Pattern represents a detected plugin-specific pattern in SQL

type PatternSeverity ΒΆ

type PatternSeverity string

PatternSeverity indicates pattern importance

const (
	SeverityCritical PatternSeverity = "CRITICAL" // Must preserve (e.g., auth functions)
	SeverityHigh     PatternSeverity = "HIGH"     // Should preserve (e.g., RLS policies)
	SeverityMedium   PatternSeverity = "MEDIUM"   // Can consolidate carefully
	SeverityLow      PatternSeverity = "LOW"      // Safe to consolidate
)

type PatternType ΒΆ

type PatternType string

PatternType categorizes detected patterns

const (
	PatternTypeAuth      PatternType = "AUTH"      // Authentication/authorization patterns
	PatternTypeORM       PatternType = "ORM"       // ORM-specific syntax
	PatternTypeSchema    PatternType = "SCHEMA"    // Schema metadata
	PatternTypeFunction  PatternType = "FUNCTION"  // Function definitions
	PatternTypePolicy    PatternType = "POLICY"    // RLS/security policies
	PatternTypeStorage   PatternType = "STORAGE"   // File storage patterns
	PatternTypeTrigger   PatternType = "TRIGGER"   // Trigger definitions
	PatternTypeExtension PatternType = "EXTENSION" // Extension usage
)

type Plugin ΒΆ

type Plugin interface {

	// Name returns the unique plugin identifier (e.g., "clerk", "supabase", "prisma")
	Name() string

	// Priority returns plugin priority for conflict resolution (higher = higher priority)
	// Standard priorities:
	//   - Auth services: 90-100
	//   - ORMs: 70-89
	//   - Platforms: 50-69
	//   - Utilities: 0-49
	Priority() int

	// Detect analyzes migrations to determine if this plugin is applicable.
	// Returns true if plugin should be activated based on migration patterns.
	Detect(migrations []*types.Migration) bool

	// Initialize configures the plugin with service-specific settings.
	// Config is the plugin-specific configuration section from pgsquash.config.json.
	Initialize(ctx context.Context, config any) error

	// EnrichStatement adds plugin-specific metadata to parsed statements.
	// Called after pg_query parsing, before tracking.
	// Examples:
	//   - Mark auth functions with AuthPattern metadata
	//   - Tag ORM-generated tables with schema preservation flags
	//   - Add cross-reference information for validation
	EnrichStatement(ctx context.Context, stmt *types.Statement) error

	// DetectPatterns analyzes SQL text for plugin-specific patterns.
	// Returns patterns found (e.g., JWT claim access, Prisma directives).
	// Called before pg_query parsing for pre-parse transformations.
	DetectPatterns(sql string) []Pattern

	// DetectAuthPattern analyzes a statement for authentication patterns.
	// Returns the auth pattern identifier (e.g., "clerk_jwt_v2", "supabase_rls")
	// or empty string if no auth pattern is detected.
	// This allows plugins to claim ownership of auth-related statements.
	DetectAuthPattern(stmt *types.Statement) string

	// TransformSQL modifies SQL statements for compatibility or optimization.
	// Called before pg_query parsing to fix syntax issues.
	// Examples:
	//   - Add STABLE markers to auth functions
	//   - Convert Prisma @@ directives to PostgreSQL equivalents
	//   - Fix ORM-specific syntax
	TransformSQL(ctx context.Context, sql string) (string, error)

	// InjectCompatibilityLayer returns SQL to execute before migrations.
	// Used to create mock functions, roles, or schemas for validation.
	// Examples:
	//   - Clerk: CREATE SCHEMA auth; CREATE FUNCTION auth.jwt() ...
	//   - Supabase: CREATE ROLE authenticated; CREATE FUNCTION auth.uid() ...
	//   - NextAuth: CREATE TABLE accounts, sessions, users, verification_tokens ...
	InjectCompatibilityLayer(ctx context.Context) string

	// FixFunctionVolatility adds IMMUTABLE/STABLE/VOLATILE markers to functions.
	// Service-specific implementation based on function patterns.
	// Returns modified SQL with volatility markers added.
	FixFunctionVolatility(ctx context.Context, functionSQL string) (string, error)

	// ValidateSchema performs plugin-specific schema validation.
	// Called after standard validation with access to database connection.
	// Examples:
	//   - Verify RLS policies reference correct auth functions
	//   - Check Prisma shadow database compatibility
	//   - Validate ORM adapter table schemas
	ValidateSchema(ctx context.Context, db *sql.DB) error

	// GetRequiredExtensions returns PostgreSQL extensions required by this plugin.
	// Examples:
	//   - Supabase: []string{"uuid-ossp"}
	//   - Vector DBs: []string{"vector"}
	GetRequiredExtensions() []string

	// GetConsolidationRules returns plugin-specific consolidation rules.
	// These rules are merged with standard consolidation rules.
	// Higher priority plugins override conflicting rules.
	GetConsolidationRules() []ConsolidationRule

	// ShouldPreserve determines if a statement should never be consolidated.
	// Returns true to mark statement as critical (e.g., auth functions, ORM metadata).
	// Examples:
	//   - Preserve Clerk JWT v2 organization functions
	//   - Preserve Prisma migration metadata tables
	//   - Preserve NextAuth session management triggers
	ShouldPreserve(stmt *types.Statement) bool

	// GetConflictingPlugins returns names of plugins that conflict with this one.
	// Used for conflict resolution when multiple plugins want to handle same pattern.
	GetConflictingPlugins() []string
}

Plugin represents a third-party service integration that can hook into the migration processing pipeline at multiple points.

Lifecycle:

  1. Registry.Detect() checks all migrations to find applicable plugins
  2. Plugin.Initialize() is called with service-specific configuration
  3. Parser calls EnrichStatement() to add metadata
  4. Transformation calls TransformSQL() to modify SQL
  5. Validation calls InjectCompatibilityLayer() and ValidateSchema()
  6. Squasher uses GetConsolidationRules() and ShouldPreserve()

func ResolveConflicts ΒΆ

func ResolveConflicts(candidates []Plugin) []Plugin

ResolveConflicts applies priority-based conflict resolution to an arbitrary set of plugins and returns the plugins that remain active, ordered by priority (highest first).

This is the exact resolution logic the registry applies during DiscoverAndInitialize: plugins are visited in descending priority order and each surviving plugin excludes every plugin named by its GetConflictingPlugins(). It is exported so public API surfaces (pkg/plugins) can report compatibility identically to the squashing pipeline.

type PolicyConsolidator ΒΆ

type PolicyConsolidator struct {
	*BaseConsolidator
}

PolicyConsolidation provides common policy consolidation helpers

func NewPolicyConsolidator ΒΆ

func NewPolicyConsolidator(name string) *PolicyConsolidator

NewPolicyConsolidator creates a new policy consolidator

func (*PolicyConsolidator) AllClausesIdentical ΒΆ

func (pc *PolicyConsolidator) AllClausesIdentical(clauses []string) bool

AllClausesIdentical checks if all clauses in a list are identical

func (*PolicyConsolidator) AllSameObjectName ΒΆ

func (pc *PolicyConsolidator) AllSameObjectName(statements []*types.Statement) bool

AllSameObjectName checks if all statements have the same object name

func (*PolicyConsolidator) AllSameObjectType ΒΆ

func (pc *PolicyConsolidator) AllSameObjectType(statements []*types.Statement, objectType types.ObjectType) bool

AllSameObjectType checks if all statements are of the same type

func (*PolicyConsolidator) AllSameTargetTable ΒΆ

func (pc *PolicyConsolidator) AllSameTargetTable(statements []*types.Statement) bool

AllSameTargetTable checks if all policy statements target the same table

func (*PolicyConsolidator) ExtractPolicyClauses ΒΆ

func (pc *PolicyConsolidator) ExtractPolicyClauses(statements []*types.Statement) ([]string, []string)

ExtractPolicyClauses extracts USING and WITH CHECK clauses from policies

func (*PolicyConsolidator) HaveSamePolicyLogic ΒΆ

func (pc *PolicyConsolidator) HaveSamePolicyLogic(statements []*types.Statement) bool

HaveSamePolicyLogic checks if policies have the same security logic

type Registry ΒΆ

type Registry struct {
	// contains filtered or unexported fields
}

Registry manages the lifecycle of all plugins

func GlobalRegistry ΒΆ

func GlobalRegistry() *Registry

GlobalRegistry returns the global plugin registry

func NewRegistry ΒΆ

func NewRegistry() *Registry

NewRegistry creates a new plugin registry

func (*Registry) ActivePlugins ΒΆ

func (r *Registry) ActivePlugins() []Plugin

ActivePlugins returns the list of currently active plugins (sorted by priority)

func (*Registry) DiscoverAndInitialize ΒΆ

func (r *Registry) DiscoverAndInitialize(ctx context.Context, migrations []*types.Migration, config map[string]any) error

DiscoverAndInitialize detects applicable plugins from migrations and initializes them This is the main entry point called by the squashing engine

func (*Registry) EnrichStatement ΒΆ

func (r *Registry) EnrichStatement(ctx context.Context, stmt *types.Statement) error

EnrichStatement calls EnrichStatement on all active plugins Plugins are called in priority order (highest first)

func (*Registry) GetConsolidationRules ΒΆ

func (r *Registry) GetConsolidationRules() []ConsolidationRule

GetConsolidationRules aggregates consolidation rules from all active plugins

func (*Registry) GetPlugin ΒΆ

func (r *Registry) GetPlugin(name string) (Plugin, bool)

GetPlugin retrieves a plugin by name

func (*Registry) GetRequiredExtensions ΒΆ

func (r *Registry) GetRequiredExtensions() []string

GetRequiredExtensions aggregates required extensions from all active plugins

func (*Registry) InjectCompatibilityLayer ΒΆ

func (r *Registry) InjectCompatibilityLayer(ctx context.Context) string

InjectCompatibilityLayer aggregates compatibility SQL from all active plugins

func (*Registry) IsActive ΒΆ

func (r *Registry) IsActive(name string) bool

IsActive checks if a plugin is currently active

func (*Registry) Register ΒΆ

func (r *Registry) Register(plugin Plugin) error

Register adds a plugin to the registry.

Registration is idempotent by plugin name: registering a plugin whose name is already present is a no-op. This allows every entry point (CLI main, pkg/engine construction, library callers) to ensure the default plugin set is registered without coordinating a single init site.

func (*Registry) Reset ΒΆ

func (r *Registry) Reset()

Reset clears all active plugins (useful for testing)

func (*Registry) ShouldPreserve ΒΆ

func (r *Registry) ShouldPreserve(stmt *types.Statement) bool

ShouldPreserve checks if any active plugin wants to preserve this statement

func (*Registry) TransformSQL ΒΆ

func (r *Registry) TransformSQL(ctx context.Context, sql string) (string, error)

TransformSQL calls TransformSQL on all active plugins Plugins are called in priority order, each transforming the output of the previous

func (*Registry) ValidateSchema ΒΆ

func (r *Registry) ValidateSchema(ctx context.Context, db *sql.DB) error

ValidateSchema calls ValidateSchema on all active plugins

type TableConsolidator ΒΆ

type TableConsolidator struct {
	*BaseConsolidator
}

TableConsolidator provides common table consolidation helpers

func NewTableConsolidator ΒΆ

func NewTableConsolidator(name string) *TableConsolidator

NewTableConsolidator creates a new table consolidator

func (*TableConsolidator) AllSameTable ΒΆ

func (tc *TableConsolidator) AllSameTable(statements []*types.Statement) bool

AllSameTable checks if all statements target the same table

func (*TableConsolidator) ConservativeMerge ΒΆ

func (tc *TableConsolidator) ConservativeMerge(statements []*types.Statement) *types.Statement

ConservativeMerge returns the first statement (conservative approach)

func (*TableConsolidator) ContainsKeyword ΒΆ

func (tc *TableConsolidator) ContainsKeyword(statements []*types.Statement, keyword string) bool

ContainsKeyword checks if any statement contains a specific keyword

func (*TableConsolidator) FilterByOperation ΒΆ

func (tc *TableConsolidator) FilterByOperation(statements []*types.Statement, op types.Operation) []*types.Statement

FilterByOperation filters statements by operation type

func (*TableConsolidator) HasCreateOperation ΒΆ

func (tc *TableConsolidator) HasCreateOperation(statements []*types.Statement) bool

HasCreateOperation checks if any statement is a CREATE operation

Directories ΒΆ

Path Synopsis
Package auth provides shared authentication compatibility layer generation for validation and testing.
Package auth provides shared authentication compatibility layer generation for validation and testing.
Package clerk provides Clerk authentication integration for pgsquash.
Package clerk provides Clerk authentication integration for pgsquash.
Package drizzle provides Drizzle ORM integration for pgsquash.
Package drizzle provides Drizzle ORM integration for pgsquash.
Package prisma provides Prisma ORM integration for pgsquash.
Package prisma provides Prisma ORM integration for pgsquash.
Package supabase provides Supabase Platform integration for pgsquash.
Package supabase provides Supabase Platform integration for pgsquash.
Package volatility provides shared function volatility marker detection and fixing.
Package volatility provides shared function volatility marker detection and fixing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL