Create Knex database migrations for the Benefriches API. Use when adding, modifying, or removing database columns/tables. Handles schema changes (create table, add/drop/rename columns), data migrations, and updates to tableTypes.d.ts.
Instalación
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Create Knex database migrations for the Benefriches API. Use when adding, modifying, or removing database columns/tables. Handles schema changes (create table, add/drop/rename columns), data migrations, and updates to tableTypes.d.ts.
effort
low
allowed-tools
Bash, Read, Write
Create Database Migration
Generate timestamped Knex migrations following project conventions.
Quick Start
Create migration: pnpm --filter api knex:new-migration {description}
Example: pnpm --filter api knex:new-migration add-column-email-to-users-table
Creates timestamped file in apps/api/src/shared-kernel/adapters/sql-knex/migrations/
Implement up() and down() functions in the generated file
Update apps/api/src/shared-kernel/adapters/sql-knex/tableTypes.d.ts if schema changes
If new table created: add table name to tablesToCleanUp in apps/api/test/tablesToCleanUp.ts (child tables before parent tables)
Run: pnpm --filter api knex:migrate-latest
Transaction Handling
Knex automatically wraps each migration in a transaction — the knex parameter in up()/down() is already a transaction object. Do NOT call knex.transaction() inside migrations.
importtype { Knex } from"knex";
exportasyncfunctionup(knex: Knex): Promise<void> {
const rows = awaitknex("table_name")
.select("id", "json_column")
.whereRaw(`json_column::json->>'field' IS NOT NULL`);
for (const row of rows) {
const data = row.json_columnasRecord<string, unknown>;
const updated = { ...data, newField: transformValue(data.oldField) };
delete (updated asRecord<string, unknown>).oldField;
awaitknex("table_name").update({ json_column: updated }).where({ id: row.id });
}
}
exportasyncfunctiondown(): void {
return; // Data migration not reversible
}
Column Types Reference
Knex Method
PostgreSQL
TypeScript
table.uuid("id")
UUID
string
table.string("name")
VARCHAR(255)
string
table.text("desc")
TEXT
string
table.boolean("flag")
BOOLEAN
boolean
table.integer("count")
INTEGER
number
table.float("amount")
REAL
number
table.timestamp("at")
TIMESTAMP
Date
table.json("data")
JSON
Record<string, unknown>
tableTypes.d.ts Updates
After schema changes, update apps/api/src/shared-kernel/adapters/sql-knex/tableTypes.d.ts:
// Add new type for new tabletypeSqlNewTable = {
id: string;
name: string;
created_at: Date;
optional_col: string | null; // nullable columns use | null
};
// Register in Tables interfacedeclaremodule"knex/types/tables" {
interfaceTables {
new_table: SqlNewTable; // table_name: SqlType
}
}
Rules:
Use snake_case for column names (matches DB)
Use | null for nullable columns (not ?:)
Use Date for timestamps (Knex converts)
Register table in Tables interface
Checklist
Migration created with pnpm --filter api knex:new-migration {description}
up() implements forward migration
down() reverses migration (or returns void if not possible)
tableTypes.d.ts updated for schema changes (new table → add SqlXxx type + register in Tables interface)
If new table created: add table name to tablesToCleanUp array in apps/api/test/tablesToCleanUp.ts (respecting deletion order: child tables before parent tables)
Migration tested: pnpm --filter api knex:migrate-latest
Rollback tested: pnpm --filter api knex:migrate-rollback