Migraciones
El uso de migraciones es opcional
Sección titulada «El uso de migraciones es opcional»Conéctate a una base de datos existente y usa modelos de inmediato — adopta el runtime de migraciones solo cuando necesites gestión del ciclo de vida del schema.
Definir migraciones
Sección titulada «Definir migraciones»Cada migración es un objeto con name, up, y opcionalmente down. Los callbacks reciben t — el builder de migraciones:
import { defineModel, defineMigration, t } from 'jsorm';
const Role = defineModel('roles', { id: t.number().primary(), name: t.string().unique(),});
const User = defineModel('users', { id: t.number().primary(), name: t.string(), email: t.string().optional(), active: t.boolean().default(true).index(), role: t.belongsTo(Role),});
const initRolesAndUsers = defineMigration({ name: 'init-roles-and-users', up: (t) => [ t.createTable(Role), t.createTable(User), ], down: (t) => [ t.dropTable('users'), t.dropTable('roles'), ],});
const addUserTimezone = defineMigration({ name: 'add-user-timezone', up: (t) => [ t.addColumn('users', 'timezone', t.string().optional()), ], down: (t) => [ t.dropColumn('users', 'timezone', { ifExists: true }), ],});Definir un migration source
Sección titulada «Definir un migration source»Un migration source agrupa un adaptador con una lista ordenada de migraciones:
import { defineMigrationSource } from 'jsorm';import { pgAdapter } from 'jsorm-pg';
const ormSource = defineMigrationSource({ adapter: pgAdapter({ name: 'main', connectionString: process.env.DATABASE_URL!, }), migrations: [initRolesAndUsers, addUserTimezone], migrationTable: 'jsorm_migrations',});Ejecutar migraciones por código
Sección titulada «Ejecutar migraciones por código»import { migrate, migrateDown } from 'jsorm';
await migrate(ormSource); // aplica todas las pendientesawait migrateDown(ormSource); // revierte el último batchOperaciones de migración (vía t)
Sección titulada «Operaciones de migración (vía t)»| Operación | Descripción |
|---|---|
t.createTable(Model) | Crea tabla desde definición de modelo |
t.dropTable(tableName) | Elimina una tabla |
t.addColumn(table, name, field) | Agrega una columna |
t.dropColumn(table, name, opts?) | Elimina una columna |
t.renameColumn(table, from, to) | Renombra una columna |
t.createIndex(table, columns) | Agrega un índice |
t.dropIndex(table, name) | Elimina un índice |
Migraciones SQL directo
Sección titulada «Migraciones SQL directo»Para DDL complejo que el builder no cubre, usa rawSql():
import { defineMigration, rawSql } from 'jsorm';
const addFullTextIndex = defineMigration({ name: 'add-fulltext-index', up: [ rawSql( "CREATE INDEX users_name_fts ON users USING GIN (to_tsvector('english', name))", 'DROP INDEX IF EXISTS users_name_fts', ), ], down: [ rawSql( 'DROP INDEX IF EXISTS users_name_fts', "CREATE INDEX users_name_fts ON users USING GIN (to_tsvector('english', name))", ), ],});CLI en modo config-first
Sección titulada «CLI en modo config-first»Cuando jsorm.config.ts tiene migrationSources + defaults.migrationSource configurados, los comandos CLI no necesitan argumentos:
jsorm migrate:status # verificar pendientesjsorm migrate # aplicar todas las pendientesjsorm migrate:up # aplicar la siguientejsorm migrate:down # revertir último batch (protegido en prod)Modo módulo-exportación (legacy)
Sección titulada «Modo módulo-exportación (legacy)»Pasa el archivo JS compilado y el nombre exportado cuando no uses config-first:
jsorm migrate ./dist/schema.js ormSourcejsorm migrate:up ./dist/schema.js ormSourcejsorm migrate:down ./dist/schema.js ormSourcejsorm migrate:status ./dist/schema.js ormSourceTabla de tracking de migraciones
Sección titulada «Tabla de tracking de migraciones»jsorm registra las migraciones aplicadas en jsorm_migrations (configurable vía migrationTable):
-- auto-gestionada, no modificar manualmenteid SERIAL PRIMARY KEYname TEXT NOT NULL UNIQUEbatch INTEGER NOT NULLapplied_at TIMESTAMP NOT NULL DEFAULT NOW()Generación automática de migraciones
Sección titulada «Generación automática de migraciones»Genera archivos de migración revisados haciendo diff de los modelos actuales contra un snapshot almacenado:
// jsorm.config.tsimport { defineMigrationGenerateSource } from 'jsorm';
export const generateSource = defineMigrationGenerateSource({ models: [Role, User], snapshotPath: '.migrations/schema.json',});Luego ejecuta:
jsorm migrate:generateEl generador clasifica cada cambio como safe, review_required o dangerous, emite un archivo de migración con timestamp, y registra las tablas many-to-many pivot detectadas.
Buenas prácticas
Sección titulada «Buenas prácticas»- Mantén las migraciones pequeñas — un concepto por migración.
- Escribe siempre
downcuando un paso no sea automáticamente reversible. - Nunca modifiques una migración ya aplicada.
- Ejecuta
migrate:statusen el deploy para confirmar que todas se aplicaron. - Trata
migrate:down,db:freshydb:rollbackcomo comandos sensibles al entorno — mantenlos fuera de la automatización de producción.