¿Qué hace convex-migration-helper?
Planifica migraciones de esquema y datos de Convex con widen-migrate-narrow y @convex-dev/migrations. Útil para cambios de esquema disruptivos, rellenos de datos, reestructuración de tablas o despliegues sin tiempo de inactividad.
Visión general
Este skill guía la creación de migraciones seguras y sin tiempo de inactividad para aplicaciones Convex. Implementa el patrón widen-migrate-narrow, que consiste en:
- Ampliar (Widen): Agregar nuevos campos o tablas sin eliminar los antiguos.
- Migrar (Migrate): Rellenar los nuevos campos con datos transformados desde los antiguos.
- Estrechar (Narrow): Eliminar los campos o tablas antiguos una vez que la migración se ha completado.
Plataformas soportadas
- Convex (cualquier proyecto que use
convex devo despliegues en producción) - Funciona con agentes de IA como Claude Code, Cursor o Codex
Cómo usar
1. Instalar dependencias
npm install @convex-dev/migrations
2. Crear un archivo de migración
Crea un archivo dentro de la carpeta convex/migrations/, por ejemplo convex/migrations/001_rename_field.ts:
import { migration } from "@convex-dev/migrations";
import { v } from "convex/values";
export default migration({
name: "rename_field",
up: async (ctx) => {
const documents = await ctx.db.query("myTable").collect();
for (const doc of documents) {
await ctx.db.patch(doc._id, {
newField: doc.oldField,
});
}
},
});
3. Ejecutar la migración
Ejecuta el script de migración con el CLI de Convex:
npx convex run migrations/001_rename_field
Patrón Widen-Migrate-Narrow en detalle
Para migraciones sin tiempo de inactividad, sigue estos pasos:
Paso 1: Ampliar
Modifica tu esquema para incluir tanto el campo antiguo como el nuevo:
// schema.ts
export default defineSchema({
myTable: defineTable({
oldField: v.string(),
newField: v.optional(v.string()), // nuevo campo
}),
});
Paso 2: Migrar
Crea una migración que transfiera los datos del campo antiguo al nuevo:
// convex/migrations/002_backfill_new_field.ts
import { migration } from "@convex-dev/migrations";
export default migration({
name: "backfill_new_field",
up: async (ctx) => {
const documents = await ctx.db.query("myTable").collect();
for (const doc of documents) {
if (!doc.newField) {
await ctx.db.patch(doc._id, {
newField: doc.oldField,
});
}
}
},
});
Paso 3: Estrechar
Una vez que todos los datos se han migrado, elimina el campo antiguo del esquema:
// schema.ts
export default defineSchema({
myTable: defineTable({
newField: v.string(), // solo el nuevo campo
}),
});
Backfills y reestructuración de tablas
Para backfills (relleno de datos) masivos, puedes usar ctx.db.query con filtros y paginación. Para reestructurar tablas (por ejemplo, dividir una tabla en dos), crea migraciones separadas para cada nueva tabla.
Ejemplo completo
Consulta el repositorio oficial de @convex-dev/migrations para más ejemplos y documentación detallada.
Notas importantes
- Siempre prueba las migraciones en un entorno de desarrollo antes de ejecutarlas en producción.
- Las migraciones deben ser idempotentes (ejecutarlas varias veces no debe causar errores).
- Usa
ctx.db.patchen lugar dectx.db.replacepara evitar sobrescribir datos no migrados.
Licencia
MIT