Database Adapters

MoroJS uses a database adapter pattern instead of ORMs. Adapters provide a unified interface for different databases with built-in connection pooling and type safety.

Available Database Adapters

PostgreSQL

Advanced relational database with full SQL support

MySQL

Popular relational database with connection pooling

SQLite

Lightweight database perfect for development

Using Database Adapters

Basic Adapter Setup

typescript

1import { createApp, createDatabaseAdapter, z, validate } from '@morojs/moro';
2
3const app = createApp({
4  cors: true,
5  compression: true
6});
7
8// Create database adapter
9const db = createDatabaseAdapter('sqlite', {
10  filename: 'app.db',
11  memory: false
12});
13
14// Initialize connection
15async function initializeDatabase() {
16  await db.connect();
17  
18  // Create tables
19  await db.query(`
20    CREATE TABLE IF NOT EXISTS users (
21      id INTEGER PRIMARY KEY AUTOINCREMENT,
22      name TEXT NOT NULL,
23      email TEXT UNIQUE NOT NULL,
24      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
25    )
26  `);
27}
28
29// User schema
30const UserSchema = z.object({
31  name: z.string().min(2).max(50),
32  email: z.string().email()
33});
34
35// Routes using adapter
36app.get('/users', async (req, res) => {
37  const users = await db.query('SELECT * FROM users');
38  return { success: true, data: users };
39});
40
41app.post('/users', 
42  validate({ body: UserSchema }),
43  async (req, res) => {
44    const newUser = await db.insert('users', req.body);
45    res.status(201);
46    return { success: true, data: newUser };
47  }
48);
49
50// Start application
51initializeDatabase().then(() => {
52  app.listen(3000);
53});

Adapter Methods

Available Methods

typescript

1// Connection management
2await db.connect();
3await db.disconnect();
4
5// Query methods
6const users = await db.query('SELECT * FROM users');
7const user = await db.queryOne('SELECT * FROM users WHERE id = ?', [1]);
8
9// CRUD operations
10const newUser = await db.insert('users', {
11  name: 'John Doe',
12  email: 'john@example.com'
13});
14
15const updatedUser = await db.update('users', 
16  { name: 'Jane Doe' }, 
17  { id: 1 }
18);
19
20const deletedCount = await db.delete('users', { id: 1 });
21
22// Transactions
23const result = await db.transaction(async (tx) => {
24  const user = await tx.insert('users', userData);
25  await tx.insert('profiles', { user_id: user.id, ...profileData });
26  return user;
27});
28
29// Batch operations
30const users = await db.batchInsert('users', [
31  { name: 'User 1', email: 'user1@example.com' },
32  { name: 'User 2', email: 'user2@example.com' }
33]);

Multiple Database Adapters

Using Multiple Databases

typescript

1// Primary database
2const primaryDb = createDatabaseAdapter('postgresql', {
3  host: 'localhost',
4  user: 'postgres',
5  password: process.env.DB_PASSWORD,
6  database: 'myapp_primary',
7  connectionLimit: 20
8});
9
10// Analytics database
11const analyticsDb = createDatabaseAdapter('mysql', {
12  host: 'analytics.example.com',
13  user: 'analytics',
14  password: process.env.ANALYTICS_PASSWORD,
15  database: 'analytics',
16  connectionLimit: 10
17});
18
19// Cache database
20const cacheDb = createDatabaseAdapter('sqlite', {
21  filename: 'cache.db'
22});
23
24// Initialize all connections
25await Promise.all([
26  primaryDb.connect(),
27  analyticsDb.connect(),
28  cacheDb.connect()
29]);
30
31// Use different databases for different purposes
32app.get('/users/:id', async (req, res) => {
33  const { id } = req.params;
34  
35  // Get user from primary database
36  const user = await primaryDb.queryOne(
37    'SELECT * FROM users WHERE id = $1', [id]
38  );
39  
40  // Get analytics from analytics database
41  const analytics = await analyticsDb.query(
42    'SELECT * FROM user_stats WHERE user_id = ?', [id]
43  );
44  
45  // Check cache
46  const cached = await cacheDb.queryOne(
47    'SELECT data FROM cache WHERE key = ?', [`user_${id}`]
48  );
49  
50  return {
51    user,
52    analytics,
53    cached: cached ? JSON.parse(cached.data) : null
54  };
55});

Adapter Comparison

FeaturePostgreSQLMySQLSQLite
PerformanceExcellentExcellentGood
ConcurrencyExcellentGoodLimited
Setup ComplexityMediumMediumSimple
Use CaseProductionProductionDevelopment
Connection PoolingBuilt-inBuilt-inN/A

Next Steps