ASD

Database Migration

Ejecuta migraciones de bases de datos entre ORMs y plataformas con estrategias zero-downtime, transformación de datos y procedimientos de rollback.

Estrellas
38.8k

en todo el repo

Actividad
47

0–100, la ruta de este skill

Actualizado
hace 2 meses

último commit aquí

Commits
1

últimos 90 días

Contexto
2k tok

66 tok en reposo

Paquete
2 archivos

10 KB

Instalar

Funciona con cualquier agente que lea SKILL.md

npx -y skills add wshobson/agents --skill database-migration --agent claude-code

Se instala solo en este repositorio.

Qué hace

  • Genera migraciones de esquema y datos para Sequelize, TypeORM y Prisma con sus comandos up/down
  • Aplica estrategias de zero-downtime para renombrar o cambiar tipos de columnas en varios pasos
  • Escribe transformaciones de datos complejas dentro de migraciones (parseo, copia, reconstrucción)
  • Implementa migraciones basadas en transacciones y rollback con tablas de respaldo (checkpoint-based)

Úsalo cuando

  • Migrar entre distintos ORMs
  • Realizar transformaciones de esquema
  • Mover datos entre bases de datos
  • Implementar procedimientos de rollback o despliegues zero-downtime

No lo uses cuando

    Qué lo activa

    Di cualquiera de estas frases y el agente debería cargar este skill.

    • Ayúdame a renombrar una columna sin downtime en Sequelize
    • Necesito migrar el esquema de TypeORM a Prisma
    • Crea una migración que transforme address_string en street, city y state
    • Quiero una estrategia de rollback con tabla de respaldo para esta migración

    SKILL.md

    En inglés

    Database Migration

    Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

    When to Use This Skill

    • Migrating between different ORMs
    • Performing schema transformations
    • Moving data between databases
    • Implementing rollback procedures
    • Zero-downtime deployments
    • Database version upgrades
    • Data model refactoring

    ORM Migrations

    Sequelize Migrations

    // migrations/20231201-create-users.js
    module.exports = {
      up: async (queryInterface, Sequelize) => {
        await queryInterface.createTable("users", {
          id: {
            type: Sequelize.INTEGER,
            primaryKey: true,
            autoIncrement: true,
          },
          email: {
            type: Sequelize.STRING,
            unique: true,
            allowNull: false,
          },
          createdAt: Sequelize.DATE,
          updatedAt: Sequelize.DATE,
        });
      },
    
      down: async (queryInterface, Sequelize) => {
        await queryInterface.dropTable("users");
      },
    };
    
    // Run: npx sequelize-cli db:migrate
    // Rollback: npx sequelize-cli db:migrate:undo
    

    TypeORM Migrations

    // migrations/1701234567-CreateUsers.ts
    import { MigrationInterface, QueryRunner, Table } from "typeorm";
    
    export class CreateUsers1701234567 implements MigrationInterface {
      public async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.createTable(
          new Table({
            name: "users",
            columns: [
              {
                name: "id",
                type: "int",
                isPrimary: true,
                isGenerated: true,
                generationStrategy: "increment",
              },
              {
                name: "email",
                type: "varchar",
                isUnique: true,
              },
              {
                name: "created_at",
                type: "timestamp",
                default: "CURRENT_TIMESTAMP",
              },
            ],
          }),
        );
      }
    
      public async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.dropTable("users");
      }
    }
    
    // Run: npm run typeorm migration:run
    // Rollback: npm run typeorm migration:revert
    

    Prisma Migrations

    // schema.prisma
    model User {
      id        Int      @id @default(autoincrement())
      email     String   @unique
      createdAt DateTime @default(now())
    }
    
    // Generate migration: npx prisma migrate dev --name create_users
    // Apply: npx prisma migrate deploy
    

    Schema Transformations

    Adding Columns with Defaults

    // Safe migration: add column with default
    module.exports = {
      up: async (queryInterface, Sequelize) => {
        await queryInterface.addColumn("users", "status", {
          type: Sequelize.STRING,
          defaultValue: "active",
          allowNull: false,
        });
      },
    
      down: async (queryInterface) => {
        await queryInterface.removeColumn("users", "status");
      },
    };
    

    Renaming Columns (Zero Downtime)

    // Step 1: Add new column
    module.exports = {
      up: async (queryInterface, Sequelize) => {
        await queryInterface.addColumn("users", "full_name", {
          type: Sequelize.STRING,
        });
    
        // Copy data from old column
        await queryInterface.sequelize.query("UPDATE users SET full_name = name");
      },
    
      down: async (queryInterface) => {
        await queryInterface.removeColumn("users", "full_name");
      },
    };
    
    // Step 2: Update application to use new column
    
    // Step 3: Remove old column
    module.exports = {
      up: async (queryInterface) => {
        await queryInterface.removeColumn("users", "name");
      },
    
      down: async (queryInterface, Sequelize) => {
        await queryInterface.addColumn("users", "name", {
          type: Sequelize.STRING,
        });
      },
    };
    

    Changing Column Types

    module.exports = {
      up: async (queryInterface, Sequelize) => {
        // For large tables, use multi-step approach
    
        // 1. Add new column
        await queryInterface.addColumn("users", "age_new", {
          type: Sequelize.INTEGER,
        });
    
        // 2. Copy and transform data
        await queryInterface.sequelize.query(`
          UPDATE users
          SET age_new = CAST(age AS INTEGER)
          WHERE age IS NOT NULL
        `);
    
        // 3. Drop old column
        await queryInterface.removeColumn("users", "age");
    
        // 4. Rename new column
        await queryInterface.renameColumn("users", "age_new", "age");
      },
    
      down: async (queryInterface, Sequelize) => {
        await queryInterface.changeColumn("users", "age", {
          type: Sequelize.STRING,
        });
      },
    };
    

    Data Transformations

    Complex Data Migration

    module.exports = {
      up: async (queryInterface, Sequelize) => {
        // Get all records
        const [users] = await queryInterface.sequelize.query(
          "SELECT id, address_string FROM users",
        );
    
        // Transform each record
        for (const user of users) {
          const addressParts = user.address_string.split(",");
    
          await queryInterface.sequelize.query(
            `UPDATE users
             SET street = :street,
                 city = :city,
                 state = :state
             WHERE id = :id`,
            {
              replacements: {
                id: user.id,
                street: addressParts[0]?.trim(),
                city: addressParts[1]?.trim(),
                state: addressParts[2]?.trim(),
              },
            },
          );
        }
    
        // Drop old column
        await queryInterface.removeColumn("users", "address_string");
      },
    
      down: async (queryInterface, Sequelize) => {
        // Reconstruct original column
        await queryInterface.addColumn("users", "address_string", {
          type: Sequelize.STRING,
        });
    
        await queryInterface.sequelize.query(`
          UPDATE users
          SET address_string = CONCAT(street, ', ', city, ', ', state)
        `);
    
        await queryInterface.removeColumn("users", "street");
        await queryInterface.removeColumn("users", "city");
        await queryInterface.removeColumn("users", "state");
      },
    };
    

    Rollback Strategies

    Transaction-Based Migrations

    module.exports = {
      up: async (queryInterface, Sequelize) => {
        const transaction = await queryInterface.sequelize.transaction();
    
        try {
          await queryInterface.addColumn(
            "users",
            "verified",
            { type: Sequelize.BOOLEAN, defaultValue: false },
            { transaction },
          );
    
          await queryInterface.sequelize.query(
            "UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",
            { transaction },
          );
    
          await transaction.commit();
        } catch (error) {
          await transaction.rollback();
          throw error;
        }
      },
    
      down: async (queryInterface) => {
        await queryInterface.removeColumn("users", "verified");
      },
    };
    

    Checkpoint-Based Rollback

    module.exports = {
      up: async (queryInterface, Sequelize) => {
        // Create backup table
        await queryInterface.sequelize.query(
          "CREATE TABLE users_backup AS SELECT * FROM users",
        );
    
        try {
          // Perform migration
          await queryInterface.addColumn("users", "new_field", {
            type: Sequelize.STRING,
          });
    
          // Verify migration
          const [result] = await queryInterface.sequelize.query(
            "SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",
          );
    
          if (result[0].count > 0) {
            throw new Error("Migration verification failed");
          }
    
          // Drop backup
          await queryInterface.dropTable("users_backup");
        } catch (error) {
          // Restore from backup
          await queryInterface.sequelize.query("DROP TABLE users");
          await queryInterface.sequelize.query(
            "CREATE TABLE users AS SELECT * FROM users_backup",
          );
          await queryInterface.dropTable("users_backup");
          throw error;
        }
      },
    };
    

    Additional patterns and templates

    More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.

    Reproducido de wshobson/agents bajo licencia MIT. Leer esta página en markdown.

    Archivos

    2 archivos en el paquete. Solo se lee SKILL.md al activarse — las referencias se cargan si el skill decide que las necesita.

    Antes de instalar

    Requiere un proyecto con Sequelize, TypeORM o Prisma ya configurado y sus respectivos CLI instalados.

    Detalles

    Creador
    wshobson
    Categoría
    Bases de datos
    Licencia
    MIT
    Recursos incluidos
    referencias
    Repositorio
    wshobson/agents
    Código fuente
    Ver SKILL.md

    Etiquetas

    Más de wshobson/agents

    Este repo incluye 180 skills. Si instalas uno, normalmente ya tienes los demás.

    Úsalo al seleccionar y colocar iconos, imágenes, SVGs, diagramas o infografías de apoyo aprobados en un PPTX editable.

    Costo de contexto al activarse
    344 tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 26 días
    documentos

    Úsalo cuando pidan optimizar un prompt, mejorar su rendimiento, diseñar una plantilla, aplicar chain-of-thought, few-shot prompting o técnicas avanzadas de prompt engineering para producción.

    Costo de contexto al activarse
    1.3k tok
    Tamaño del paquete
    10 archivos
    Última actualización
    el mes pasado
    herramientas desarrollo

    Úsalo al redactar o reparar una especificación JSON con coordenadas explícitas para un PPTX editable.

    Costo de contexto al activarse
    489 tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 26 días
    documentos

    Úsalo para validar o reparar un PPTX editable en cuanto a geometría, accesibilidad, editabilidad nativa, linaje de fuente e integridad del paquete OOXML.

    Costo de contexto al activarse
    409 tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 26 días
    documentos

    Úsalo para analizar un PPTX de referencia en modo solo lectura: estructura, tema, tipografía, ritmo de layout, diagnósticos, catálogos de plantillas derivados o inspección segura del paquete OOXML.

    Costo de contexto al activarse
    689 tok
    Tamaño del paquete
    8 archivos
    Última actualización
    hace 26 días
    documentos

    Úsalo al preparar la narrativa, las fuentes y el contexto de diseño para un nuevo deck PPTX editable.

    Costo de contexto al activarse
    415 tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 26 días
    documentos

    Skills relacionados

    Domina la optimización de consultas SQL, estrategias de indexado y análisis EXPLAIN para mejorar drásticamente el rendimiento de la base de datos y eliminar consultas lentas.

    Costo de contexto al activarse
    1.5k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 2 meses
    bases de datos

    Diseña e implementa event stores para sistemas de event sourcing: infraestructura, elección de tecnología y patrones de persistencia de eventos.

    Costo de contexto al activarse
    1k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 2 meses
    bases de datos

    Testea contratos inteligentes de forma exhaustiva con Hardhat y Foundry: tests unitarios, de integración y forking de mainnet.

    Costo de contexto al activarse
    2k tok
    Tamaño del paquete
    2 archivos
    Última actualización
    hace 2 meses
    testing qa