Codegen System Overview
Purpose: Understand the codegen architecture and design
Last Updated: 2024-11-28
What is Codegen?
The codegen system automatically generates type-safe TypeScript wrappers for PostgreSQL functions by introspecting your database schema. This eliminates manual type definitions and ensures your application code stays in sync with your database.
Architecture
High-Level Flow
PostgreSQL Database
↓ (1) introspection
Type Catalog (src/lib/codegen/introspection/)
↓ (2) schema generation
Zod Schemas (src/lib/codegen/builders/)
↓ (3) function generation
TypeScript Wrappers (src/__generated__/)
↓ (4) application usage
Application Code
Key Components
1. Introspection Layer (src/lib/codegen/introspection/)
- Queries
pg_catalogfor types and functions - Builds type dependency graphs
- Resolves composite types, enums, domains
- Key classes:
IntrospectionBootstrap,TypeCatalog,FunctionCatalog
2. Schema Generation (src/lib/codegen/builders/)
- Converts PostgreSQL types to Zod schemas
- Handles base types, composites, arrays, enums
- Generates runtime validators
- Key classes:
EnumBuilder,DomainBuilder,CompositeBuilder
3. Function Wrappers (src/lib/codegen/core/)
- Creates TypeScript functions for SQL functions
- Adds parameter validation
- Types return values
- Key classes:
FunctionGenerator,InvocationGenerator
4. Output Organization (src/__generated__/)
- Organized by PostgreSQL schema
- Index files for easy imports
- TypeScript path alias:
@db
Generated Code Structure
Directory Layout
src/__generated__/
├── index.ts # Main exports (all schemas)
├── README.md # Generated code notes
├── audit/ # audit schema functions
│ ├── index.ts # Schema exports
│ └── types.ts # Type definitions
├── auth/ # auth schema functions
│ ├── index.ts
│ └── types.ts
├── graph/ # graph schema functions
│ ├── index.ts
│ └── types.ts
└── studio/ # studio schema functions
├── index.ts
└── types.ts
Import Aliasing
Configuration (tsconfig.json):
{
"compilerOptions": {
"paths": {
"@db": ["./src/__generated__/index.ts"],
"@db/*": ["./src/__generated__/*"]
}
}
}
Usage:
// Import all schemas
import { studio, auth, graph } from '@db';
// Import specific schema
import { createResource, getResource } from '@db/graph';
// Import types
import type { NodeData } from '@db/graph/types';
Design Principles
1. Type Safety First
Compile-time checks:
// ✅ Valid - types enforced
await createResource(client, {
p_type_namespace: 'test.user',
p_external_id: 'user-1'
});
// ❌ Compile error - missing required parameter
await createResource(client, {
p_external_id: 'user-1'
});
2. Runtime Validation
Zod validates inputs:
try {
await createResource(client, {
p_type_namespace: untrustedInput,
p_data: userProvidedData
});
} catch (error) {
if (error instanceof ZodError) {
console.error('Invalid input:', error.errors);
}
}
3. Single Source of Truth
Database schema drives TypeScript types:
- Change SQL function → run codegen → TypeScript updates
- No manual type definitions to maintain
- No drift between database and application
4. Developer Experience
Clean, intuitive API:
- Named parameters (not positional)
- Optional parameters with defaults
- Clear error messages
- IDE autocomplete support
Codegen Process
Step 1: Introspection
Query PostgreSQL system catalogs to discover types and functions
Step 2: Type Resolution
Resolve type dependencies using topological sort
Step 3: Schema Generation
Generate Zod schemas for all discovered types
Step 4: Function Wrapper Generation
Generate TypeScript functions with validation
Benefits
1. Eliminates Manual Work
- No manual type definitions
- No manual validation code
- No manual wrapper functions
2. Prevents Runtime Errors
- Type mismatches caught at compile time
- Invalid inputs caught by Zod
- Database schema changes break builds
3. Improves Developer Experience
- Autocomplete for all functions
- Inline documentation from SQL comments
- Clear error messages
4. Enables Safe Refactoring
- Change SQL function signature
- Run codegen
- TypeScript compiler finds all call sites
- Update code with confidence
5. Maintains Consistency
- Single source of truth (database)
- No drift between layers
- Always in sync
Integration Points
Database Layer
Requires:
withClientfor connection managementPoolClientinstances- Transaction support
Application Layer
Provides:
- Type-safe function calls
- Runtime validation
- Clean API
See: Function Wrappers
Testing
Supports:
- Mock-friendly architecture
- Type-safe test fixtures
- Integration testing
See: Function Patterns
Performance Considerations
Codegen Performance
- Introspection: ~100-500ms per schema
- Generation: ~50-200ms per schema
- Total: Usually under 1 second for entire project
Not a bottleneck - runs once when schema changes.
Runtime Performance
Generated code is zero-overhead:
- Direct
client.query()calls - Minimal Zod validation overhead
- No abstraction layers
Limitations
What Works Well
- ✅ Base PostgreSQL types
- ✅ Composite types (records)
- ✅ Enums
- ✅ Arrays
- ✅ Domains with simple constraints
- ✅ User-defined functions
- ✅ Table-returning functions
Current Limitations
- ⚠️ Complex CHECK constraints (parsed best-effort)
- ⚠️ Some PostgreSQL-specific types (geometric, network)
- ⚠️ Triggers and dynamic constraints
- ⚠️ Overloaded functions (uses first signature)
Next Steps
- Learn Usage: See Usage for CLI commands
- Understand Types: See Type System for mappings
- View Examples: See Examples for code samples
- Troubleshoot: See Troubleshooting for issues
Related Documentation
- Usage - Running codegen
- CLI Reference - Command options
- Type System - Type mappings
- Introspection - Introspection details
- Schema Generation - Builder details
- Function Wrappers - Using generated code
- Examples - Code examples
Key Takeaway: Codegen bridges the gap between PostgreSQL and TypeScript, providing type safety without manual work.