Persistent Layer
The persistent layer manages data using Drizzle ORM for type-safe database access and the Repository pattern for data abstraction.
Architecture Overview
┌─────────────────────────────────────────────────────────┐
│ Application │
├─────────────────────────────────────────────────────────┤
│ Controllers → Services → Repositories → Database │
└─────────────────────────────────────────────────────────┘
▲
│
┌────────────────┴────────────────┐
│ │
┌─────┴─────┐ ┌───────┴───────┐
│ Models │ │ DataSources │
│ (Schema) │ │ (Connection) │
└───────────┘ └───────────────┘Core Components
| Component | Description | Learn More |
|---|---|---|
| Models | Define data structure with Drizzle schemas and relations | Models Guide |
| DataSources | Manage database connections with auto-discovery | DataSources Guide |
| Repositories | Provide type-safe CRUD operations | Repositories Guide |
| Transactions | Handle atomic multi-step operations | Transactions Guide |
Quick Example
typescript
// 1. Define a Model
@model({ type: 'entity' })
export class User extends BaseEntity<typeof User.schema> {
static override schema = pgTable('User', {
...generateIdColumnDefs({ id: { dataType: 'string' } }),
name: text('name').notNull(),
email: text('email').notNull(),
});
static override relations = () => [];
}
// 2. Create a DataSource
@datasource({ driver: 'node-postgres' })
export class PostgresDataSource extends BaseDataSource<TNodePostgresConnector, IDSConfigs> {
constructor() {
super({
name: PostgresDataSource.name,
config: {
host: process.env.POSTGRES_HOST ?? 'localhost',
port: +(process.env.POSTGRES_PORT ?? 5432),
database: process.env.POSTGRES_DATABASE ?? 'mydb',
user: process.env.POSTGRES_USER ?? 'postgres',
password: process.env.POSTGRES_PASSWORD ?? '',
},
});
}
override configure(): ValueOrPromise<void> {
const schema = this.getSchema();
this.pool = new Pool(this.settings);
this.connector = drizzle({ client: this.pool, schema });
}
}
// 3. Create a Repository
@repository({ model: User, dataSource: PostgresDataSource })
export class UserRepository extends DefaultCRUDRepository<typeof User.schema> {
async findByEmail(opts: { email: string }) {
return this.findOne({ filter: { where: { email: opts.email } } });
}
}
// 4. Use in Application
export class Application extends BaseApplication {
preConfigure() {
this.dataSource(PostgresDataSource);
this.repository(UserRepository);
}
}Next Steps
- Models - Learn how to define your data structure
- DataSources - Configure database connections
- Repositories - Master CRUD operations and queries
- Transactions - Handle atomic operations
Deep Dive: See Repository Reference for advanced filtering, relations, and operators.
See Also
Persistent Layer Topics:
- Models - Entity definitions and schemas
- DataSources - Database connections
- Repositories - Data access layer
- Transactions - Atomic operations
Related Concepts:
- Services - Use repositories for business logic
- Application - Registering persistent resources
References:
- Models API - Complete models reference
- DataSources API - Complete datasources reference
- Repositories API - Complete repositories reference
- Filter System - Query operators
External Resources:
- Drizzle ORM Documentation - ORM guide
Tutorials:
- Building a CRUD API - Complete persistence example
- E-commerce API - Advanced persistence patterns