DataSources
A DataSource manages database connections and supports schema auto-discovery from repositories.
PostgreSQL First
IGNIS currently focuses on PostgreSQL as the primary database. Support for other database systems (MySQL, SQLite, etc.) is planned for future releases.
Creating a DataSource
typescript
// src/datasources/postgres.datasource.ts
import {
BaseDataSource,
datasource,
ValueOrPromise,
} from '@venizia/ignis';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
interface IDSConfigs {
host: string;
port: number;
database: string;
user: string;
password: string;
}
@datasource({ driver: 'node-postgres' })
export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
constructor() {
super({
name: PostgresDataSource.name,
config: {
host: process.env.APP_ENV_POSTGRES_HOST ?? 'localhost',
port: +(process.env.APP_ENV_POSTGRES_PORT ?? 5432),
database: process.env.APP_ENV_POSTGRES_DATABASE ?? 'mydb',
user: process.env.APP_ENV_POSTGRES_USERNAME ?? 'postgres',
password: process.env.APP_ENV_POSTGRES_PASSWORD ?? '',
},
// No schema needed - auto-discovered from @repository bindings!
});
}
override configure(): ValueOrPromise<void> {
// getSchema() auto-discovers models from @repository bindings
const schema = this.getSchema();
this.logger.debug(
'[configure] Auto-discovered schema | Keys: %o',
Object.keys(schema),
);
this.pool = new Pool(this.settings);
this.connector = drizzle({ client: this.pool, schema });
}
override getConnectionString(): ValueOrPromise<string> {
const { host, port, user, password, database } = this.settings;
return `postgresql://${user}:${password}@${host}:${port}/${database}`;
}
}How auto-discovery works:
@repositorydecorators register model-datasource bindings in theMetadataRegistry- When
configure()is called,getSchema()invokesdiscoverSchema()which callsMetadataRegistry.buildSchema({ dataSource })to collect all bound models and their relations - Drizzle is initialized with the complete schema (tables + Drizzle relations)
You can disable auto-discovery per datasource via @datasource({ driver: 'node-postgres', autoDiscovery: false }).
Manual Schema (Optional)
If you need explicit control, you can still provide schema manually:
typescript
@datasource({ driver: 'node-postgres' })
export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
constructor() {
super({
name: PostgresDataSource.name,
config: { /* ... */ },
schema: {
User: User.schema,
Configuration: Configuration.schema,
// Add relations if using Drizzle's relational queries
},
});
}
}DataSource Hierarchy
AbstractDataSource extends BaseHelper
└── BaseDataSource
├── configure() # Setup pool + Drizzle connector (abstract)
├── getConnectionString() # Build connection URL (abstract)
├── getSchema() # Auto-discover from @repository bindings
├── discoverSchema() # Internal: reads MetadataRegistry
├── hasDiscoverableModels() # Check if any repos reference this DS
├── beginTransaction(opts?) # Start transaction with isolation level
├── getConnector() # Get Drizzle connector
└── getSettings() # Get connection configRegistering a DataSource
typescript
// src/application.ts
export class Application extends BaseApplication {
preConfigure(): ValueOrPromise<void> {
this.dataSource(PostgresDataSource);
}
}DataSources are bound as singletons to ensure connection pool sharing across the application.
Supported Drivers
| Driver | Package | Status |
|---|---|---|
node-postgres | pg | Supported |
mysql2 | mysql2 | Planned |
better-sqlite3 | better-sqlite3 | Planned |
DataSource Template
typescript
import { BaseDataSource, datasource, ValueOrPromise } from '@venizia/ignis';
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
interface IDSConfigs {
host: string;
port: number;
database: string;
user: string;
password: string;
}
@datasource({ driver: 'node-postgres' })
export class PostgresDataSource extends BaseDataSource<IDSConfigs> {
constructor() {
super({
name: PostgresDataSource.name,
config: {
host: process.env.APP_ENV_POSTGRES_HOST ?? 'localhost',
port: +(process.env.APP_ENV_POSTGRES_PORT ?? 5432),
database: process.env.APP_ENV_POSTGRES_DATABASE ?? 'mydb',
user: process.env.APP_ENV_POSTGRES_USERNAME ?? 'postgres',
password: process.env.APP_ENV_POSTGRES_PASSWORD ?? '',
},
});
}
override configure(): ValueOrPromise<void> {
const schema = this.getSchema();
this.pool = new Pool(this.settings);
this.connector = drizzle({ client: this.pool, schema });
}
override getConnectionString(): ValueOrPromise<string> {
const { host, port, user, password, database } = this.settings;
return `postgresql://${user}:${password}@${host}:${port}/${database}`;
}
}Deep Dive: See BaseDataSource Reference for connection pooling and advanced configuration.
See Also
Related Concepts:
- Repositories - Use DataSources for database access
- Models - Entity schemas loaded by DataSource
- Transactions - Multi-operation database transactions
- Application - Registering DataSources
References:
- BaseDataSource API - Complete API reference
- Environment Variables - Configuration management
External Resources:
- Drizzle ORM Documentation - ORM configuration
- node-postgres Documentation - Connection pooling guide
Best Practices:
- Performance Optimization - Connection pool tuning
- Security Guidelines - Database credential management
Tutorials:
- Complete Installation - Database setup
- Building a CRUD API - DataSource configuration