Ir al contenido

Adaptadores

La capa de adaptadores aísla el ciclo de vida de conexiones, ejecución de queries, transacciones y health checks del núcleo del ORM. El paquete core no tiene dependencias de drivers de base de datos.

Cada connection source se define con defineConnectionSource() y se registra en defineJsormConfig():

// jsorm.config.ts
import { defineConnectionSource, defineJsormConfig } from 'jsorm';
import { pgAdapter } from 'jsorm-pg';
const main = defineConnectionSource({
adapter: pgAdapter({
name: 'main',
connectionString: process.env.DATABASE_URL!,
pool: {
min: 2,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
},
}),
});
export default defineJsormConfig({
connectionSources: { main },
defaults: { connectionSource: 'main' },
});

Requiere peer dependency pg:

Ventana de terminal
pnpm add jsorm-pg pg

Define múltiples connection sources con nombre y apúntalos con jsorm.use() o jsorm.with():

// jsorm.config.ts
export default defineJsormConfig({
connectionSources: { main, analytics, cache },
defaults: { connectionSource: 'main' },
});

Apunta a un source específico en runtime:

import { jsorm } from 'jsorm';
// use() retorna un cliente con scope (sin mutación global)
const rows = await jsorm.use('analytics').get(Event, {
select: { id: true, type: true },
pagination: { perPage: 100, currentPage: 1 },
});
// with() hace scope de un callback y libera automáticamente
await jsorm.with('cache', async (cacheDb) => {
await cacheDb.executeSql('SELECT 1');
});

Usa jsorm.healthCheck() para verificar conectividad — útil en readiness probes:

const health = await jsorm.healthCheck();
// { main: 'ok', analytics: 'ok', cache: 'ok' }

También disponible vía CLI:

Ventana de terminal
jsorm db:check
await jsorm.transaction(async (tx) => {
await tx.insert(User, {
name: 'Alice',
createdAt: new Date(),
role: { connect: 1 },
});
await tx.update(Role, {
data: { name: 'member' },
where: { id: { eq: 1 } },
});
// revierte automáticamente si cualquiera lanza error
});

Si tu aplicación ya gestiona su propio pool o ciclo de vida de conexiones, usa createPooledAdapter:

import {
defineConnectionSource,
defineJsormConfig,
createPooledAdapter,
type DBRow,
} from 'jsorm';
import { Pool, type PoolClient } from 'pg';
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const adapter = createPooledAdapter<Pool, PoolClient>({
name: 'main',
connect: async () => pool,
disconnect: async (p) => p.end(),
getConnection: async (p) => p.connect(),
releaseConnection: async (c) => c.release(),
query: async (c, sql, params): Promise<readonly DBRow[]> => {
const result = await c.query(sql, [...params]);
return result.rows as readonly DBRow[];
},
transaction: async (p, run) => {
const c = await p.connect();
try {
await c.query('BEGIN');
const result = await run(c);
await c.query('COMMIT');
return result;
} catch (e) {
await c.query('ROLLBACK');
throw e;
} finally {
c.release();
}
},
metadata: {
dialect: 'postgres',
driver: 'pg',
packageName: 'custom',
peerDependencies: ['pg'],
capabilities: { pooling: true, transactions: true, healthCheck: true },
},
});
  • Los adaptadores se inicializan en la primera query — los pools no se abren hasta que se usan.
  • Los pools se reutilizan entre queries en el mismo proceso.
  • Llama jsorm.close() durante el apagado graceful para drenar todos los pools activos.
  1. Nunca crees un nuevo adaptador por request — siempre reutiliza.
  2. Usa jsorm.use('name') para lecturas cross-database ocasionales; usa jsorm.with('name', fn) para patrones de callback con scope.
  3. Usa jsorm.healthCheck() en endpoints de readiness y verificación de deploys.
  4. Activa JSORM_DEBUG=1 en desarrollo local para registrar resolución de config y eventos de pool.