Ir al contenido

Primeros pasos

Esta guía recorre el flujo completo: configurar jsorm.config.ts, definir modelos, crear una instancia runtime y ejecutar queries tipadas.

  1. Define modelos

    Importa defineModel y t. Una sola definición controla inferencia TypeScript y metadatos runtime.

    // src/schema/main/user.ts
    import { defineModel, t } from '@jsorm/core';
    export const Role = defineModel('roles', {
    id: t.number().primary(),
    name: t.string().unique(),
    });
    export const User = defineModel('users', {
    id: t.number().primary(),
    name: t.string(),
    email: t.string().optional(),
    active: t.boolean().default(true),
    createdAt: t.date(),
    role: t.belongsTo(Role),
    });

    Exporta tipos inferidos cuando los necesites:

    import type { InferInput, InferModel } from '@jsorm/core';
    type UserRecord = InferModel<typeof User>;
    type UserInput = InferInput<typeof User>;
  2. Crea jsorm.config.ts

    Mantén una sola config para runtime + CLI:

    // jsorm.config.ts
    import { defineConnectionSource, defineJsormConfig } from '@jsorm/core';
    import { pgAdapter } from '@jsorm/pg';
    const main = defineConnectionSource({
    adapter: pgAdapter({
    name: 'main',
    connectionString: process.env.DATABASE_URL!,
    pool: { min: 2, max: 10 },
    }),
    });
    export default defineJsormConfig({
    connectionSources: { main },
    defaults: {
    connectionSource: 'main',
    },
    });
  3. Crea una instancia runtime

    Usa createJsorm() para los límites runtime en Node:

    import { createJsorm } from '@jsorm/core';
    const db = await createJsorm().init();

    Si ejecutaste pnpm exec jsorm init, también puedes partir del helper generado en db.ts.

  4. Inserta datos

    await db.insert(User, {
    name: 'Alice',
    email: 'alice@example.com',
    createdAt: new Date(),
    role: { connect: 1 },
    });
  5. Lee datos tipados

    const users = await db.get(User, {
    select: {
    id: true,
    name: true,
    role: { name: true },
    },
    where: {
    active: true,
    role: { name: { eq: 'admin' } },
    },
    orderBy: [{ name: 'asc' }],
    });
    // users: Array<{ id: number; name: string; role: { name: string } }>
  6. Actualiza y elimina con seguridad

    where es obligatorio en escrituras.

    await db.update(User, {
    data: { active: false },
    where: { id: { eq: 10 } },
    });
    await db.delete(User, {
    where: { id: { eq: 10 } },
    });

Usa solo el escape hatch namespaced: db.raw.*.

const rows = await db.raw.execute(
'SELECT COUNT(*) AS total FROM users WHERE active = $1',
[true],
);
const compiled = await db.raw.compile(
'SELECT id, name FROM users WHERE active = $1',
[true],
);
const health = await db.healthCheck();
// { main: 'ok' }
process.on('SIGTERM', async () => {
await db.close();
process.exit(0);
});

Para tests aislados, usa createJsormTest():

import { createJsormTest } from '@jsorm/core';
const testDb = await createJsormTest().init();
  1. Usa createJsorm() desde @jsorm/core en runtime Node, o desde @jsorm/runtime en código edge/fetch-only.
  2. Usa createJsormTest() para aislar tests en lugar de compartir estado runtime de la app.
  3. Mantén cláusulas where explícitas en todas las escrituras.
  4. Usa el DSL JSON como camino por defecto; reserva db.raw.* para casos realmente necesarios.
  5. Mantén CLI, migraciones y deploy bajo @jsorm/node.