how-to-write-typeorm-migrations-in-packmind-12ca9d — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited how-to-write-typeorm-migrations-in-packmind-12ca9d (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Write TypeORM migrations in the Packmind monorepo to manage database schema changes effectively while ensuring proper logging and rollback capabilities.
IMPORTANT: Always create migration files using the TypeORM CLI command. Never create migration files manually. The CLI automatically generates a timestamp prefix and sets up the basic structure.
# Create new migration file (TypeORM will automatically add timestamp)
npx typeorm migration:create packages/migrations/src/migrations/DescriptiveNameImplement the migration class with PackmindLogger for comprehensive logging. Include try-catch blocks and log start, progress, completion, and any errors.
import { MigrationInterface, QueryRunner } from 'typeorm';
import { PackmindLogger, LogLevel } from '@packmind/shared';
export class YourMigrationName1234567890 implements MigrationInterface {
private readonly logger = new PackmindLogger(
'YourMigrationName1234567890',
LogLevel.DEBUG,
);
public async up(queryRunner: QueryRunner): Promise<void> {
this.logger.info('Starting migration: YourMigrationName');
try {
// Your migration logic here
this.logger.info('Migration YourMigrationName completed successfully');
} catch (error) {
this.logger.error('Migration YourMigrationName failed', {
error: error.message,
});
throw error;
}
}
public async down(queryRunner: QueryRunner): Promise<void> {
this.logger.info('Starting rollback: YourMigrationName');
try {
// Your rollback logic here
this.logger.info('Rollback YourMigrationName completed successfully');
} catch (error) {
this.logger.error('Rollback YourMigrationName failed', {
error: error.message,
});
throw error;
}
}
}Use TypeORM Table class with shared helper columns (uuidMigrationColumn, timestampsMigrationColumns) from @packmind/shared to create new tables with consistent structure.
import { MigrationInterface, QueryRunner, Table } from 'typeorm';
import {
timestampsMigrationColumns,
uuidMigrationColumn,
} from '@packmind/shared/src/database/migrationColumns';
export class CreateYourTable1234567890 implements MigrationInterface {
private readonly table = new Table({
name: 'your_table',
columns: [
uuidMigrationColumn, // Standard UUID primary key
{
name: 'name',
type: 'varchar',
},
{
name: 'description',
type: 'text',
isNullable: true,
},
...timestampsMigrationColumns, // created_at, updated_at
],
});
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(this.table);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable(this.table);
}
}Use TableColumn class for adding individual columns or raw SQL for multiple columns. Always make new columns nullable initially for backward compatibility.
// Single column with TableColumn
import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm';
export class AddColumnsToTable1234567890 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.addColumn(
'your_table',
new TableColumn({
name: 'new_column',
type: 'varchar',
isNullable: true,
}),
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropColumn('your_table', 'new_column');
}
}
// Multiple columns with raw SQL
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
ALTER TABLE "your_table"
ADD COLUMN "column1" varchar NULL,
ADD COLUMN "column2" varchar NULL,
ADD COLUMN "column3" varchar NULL
`);
}Create foreign key relationships using TableForeignKey class with proper cascade behavior. Always handle foreign keys before dropping related tables.
import { MigrationInterface, QueryRunner, TableForeignKey } from 'typeorm';
export class AddForeignKey1234567890 implements MigrationInterface {
private readonly foreignKey = new TableForeignKey({
columnNames: ['parent_id'],
referencedColumnNames: ['id'],
referencedTableName: 'parent_table',
onDelete: 'CASCADE',
});
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createForeignKey('child_table', this.foreignKey);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropForeignKey('child_table', this.foreignKey);
}
}Execute migrations using npm scripts for both local development and Docker environments. Test both up and down migrations.
# Local development
npm run typeorm migration:run
npm run typeorm migration:revert
npm run typeorm migration:show
# Docker environment
npm run typeorm migration:run -- -d datasourceDocker.tsAlways include comprehensive logging with PackmindLogger, wrap operations in try-catch blocks, write reversible migrations with corresponding down operations, use descriptive names with verbs (Add, Remove, Update, Create, Drop), and handle foreign key dependencies properly when dropping tables.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.