本文へ移動
cccskills
無料GitHub で公開

typeorm-migrations

Creating TypeORM database migrations. Use when schema changes are needed (new columns, tables, indexes, constraints).

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-coreスター 34(GitHub 34 + cccskills 0)
連携ツールPostgreSQL

実行スコア 未検証

インストール方法を見る

含まれるファイル(1)

  • SKILL.md7.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

TypeORM Database Migrations

Golden Rule

Never write migration files by hand. Always auto-generate them from TypeORM entity changes. Never edit a generated migration — if it's wrong, fix the entity and regenerate.

Entity Rules — The Source of Truth

TypeORM entities (Records) are the single source of truth for the database schema. Everything must be expressed through decorators. If a constraint, index, or FK exists in the database but not in an entity decorator, TypeORM will try to drop it on the next migration:generate.

Relations define constraints, not loading behavior

@ManyToOne creates a foreign key constraint in the database. It does NOT mean the relation is eagerly loaded — relations are lazy by default. You control loading per-query via relations: { ... }.

Always define @ManyToOne when a column references another table, even if you never load the relation object:

// CORRECT — column + relation = FK constraint in DB
@Column({ name: 'integration_id', type: 'varchar' })
integrationId: string;

@ManyToOne(() => McpIntegrationRecord, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'integration_id' })
integration: McpIntegrationRecord;

// WRONG — plain column = no FK, no referential integrity
@Column({ name: 'integration_id', type: 'varchar' })
integrationId: string;

All constraints must use decorators

DB conceptDecorator
Foreign key@ManyToOne / @OneToOne + @JoinColumn
Unique constraint (full)@Unique([...]) on class
Unique constraint (partial)@Index([...], { unique: true, where: '...' }) on class
Check constraint@Check('name', 'expression') on class
Index@Index() on property or @Index([...]) on class
Enum column@Column({ type: 'enum', enum: MyEnum })

Partial unique indexes (with WHERE clause) cannot use @Unique — use @Index with unique: true and where instead.

If you add a value to a TypeScript enum used in @Column({ type: 'enum' }), you must generate a migration.

Never hand-write constraint names

TypeORM generates deterministic constraint/index names. Hand-written names (e.g. FK_my_custom_name) will mismatch, causing perpetual drift.

Workflow

1. Modify the Entity

Change the record file. Extend BaseRecord for id, createdAt, updatedAt:

@Entity('agents')
export class AgentRecord extends BaseRecord {
  @Column({ type: 'varchar', length: 255, nullable: true })
  marketplaceSlug: string | null;
}

2. Generate the Migration

The dev stack must be running (./dev status).

pnpm run migration:generate:dev src/db/migrations/DescriptiveMigrationName

No -- before the path. pnpm forwards the trailing path straight to the script. Adding a -- separator makes pnpm swallow the path, so TypeORM sees zero arguments and aborts with Nicht genügend Argumente ohne Optionen: 0 vorhanden, mindestens 1 benötigt (ELIFECYCLE Command failed with exit code 1). Pass the path with no --.

3. Review the Generated Migration

  • Contains only the expected changes (no unrelated drift)
  • up() and down() are symmetric
  • No hand-written constraint or index names

If the migration contains unexpected drift, the local DB is out of sync. Rebuild it — do not hand-author a migration to reconcile. See "Fixing Migration Drift" below.

4. Run the Migration

pnpm run migration:run:dev

5. Verify Zero Drift

pnpm run migration:generate:dev src/db/migrations/VerifyNoDrift

This must print No changes in database schema were found. If it generates a file, entities and migrations are still out of sync — investigate before committing.

6. Validate

pnpm exec tsc --noEmit
pnpm run test

Naming Convention

PascalCase describing the change:

ChangeMigration Name
Add a columnAddMarketplaceSlugToAgents
Create a tableCreateTeamSharesTable
Add an indexAddIndexOnThreadCreatedAt
Remove a columnRemoveUserShareScope
Add a constraintCascadeDeleteSharesOnScopeDelete

Fixing Migration Drift

"Drift" here means: entities on the branch, the migration files, and the local Postgres schema no longer agree. Typical triggers:

  • Switching between branches whose migration sets diverge (slot's Postgres volume was written by branch A, you're now on branch B).
  • pnpm run migration:generate:dev produces surprise changes (removes/renames on things you never touched, or resurrects columns).
  • Backend refuses to start with errors like error: relation "<table>" already exists (PG code 42P07) or column "..." of relation "..." does not exist.

Rule: rebuild the database from scratch. Do not hand-author a reconciliation migration. Hand-written reconciliation migrations poison the migration history for every teammate and every future deploy — they are worse than the drift they were meant to fix.

The rebuild

Shut the stack down and spin the DB up on an empty volume, then let migrations replay from zero:

# 1. Shut the stack down completely (from any worktree)
./dev down

# 2. Wipe the slot's Postgres volume so ./dev up starts from an empty DB.
#    Without -v the volume survives and the drift returns immediately.
docker compose -p ayunis-dev-<SLOT> down -v

# 3. Bring the stack back up — ./dev up replays every migration from scratch
./dev up --slot <SLOT>

# 4. Optional: reseed fixtures (see seed-database skill)
cd ayunis-core-backend && pnpm run seed:minimal:ts

<SLOT> is the slot number this worktree uses — the same one you passed to ./dev up. See the dev-environment skill for slot conventions.

After the rebuild

Verify zero drift before making further changes:

cd ayunis-core-backend
pnpm run migration:generate:dev src/db/migrations/VerifyNoDrift
# Must print: "No changes in database schema were found"

If a VerifyNoDrift file is produced, entities and migrations are genuinely out of sync — that's a legitimate migration to generate (via TypeORM), not to hand-write. Investigate which entity changed and, if the fix belongs in an earlier migration, edit that migration's entity source, not the reconciliation file.

Anti-Patterns

Don'tWhyInstead
Write migration SQL by handDrift between entities and schemaModify the entity, then auto-generate
Hand-author a migration to reconcile driftPoisons migration history for teammates and deploysRebuild the DB (./dev down + wipe volume + ./dev up)
Edit a generated migrationConstraint names will mismatchFix the entity and regenerate
Hand-write FK/index/constraint namesPerpetual drift on future generatesLet TypeORM name everything
Use @Column for a FK without @ManyToOneNo FK in the database, no referential integrityAdd @ManyToOne + @JoinColumn
Add enum values without a migrationDB enum won't match TypeScript enumGenerate a migration after adding values
Use @Unique for partial constraintsProduces full constraint, not partialUse @Index({ unique: true, where: '...' })
Skip zero-drift verificationEntities and migrations may still be misalignedAlways verify after running
Commit without runningMay fail at runtimeAlways migration:run:dev first

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

コメント

ログインなしで書き込めます。使ってみた感想、質問、動かなかった環境などを気軽にどうぞ。

まだコメントはありません。最初のコメントを書いてみませんか。

送信するとすぐに公開されます。メールアドレスや電話番号などの個人情報は書かないでください。URL は 2 つまでです。

0 / 1000 文字

このフォームは reCAPTCHA で保護されており、Google のプライバシーポリシーと利用規約が適用されます。

同じリポジトリのスキル

Query Ayunis deployed-environment telemetry in AppSignal — incidents, occurrence counts and error traces via the `appsignal-cli` binary; structured log attributes (user.id, org.id, nestjs.context, custom metadata) via the v2 logs API. Use when investigating a production/staging incident or log data — NOT for local dev logs (see backend-debugging).

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

Ayunis Core backend specifics — module boundaries, key files, and project conventions. Complements the nestjs-hexagonal-backend skill.

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

Frontend development in ayunis-core. Use when creating, modifying, or debugging frontend code (React, Feature-Sliced Design, API client).

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

Debug backend runtime errors (500s, crashes, unexpected behavior). Use when something is broken at runtime — not for writing new code.

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

Shared test fixtures for backend specs — port mock factories, domain builders, and shared IDs in a per-module testing/ folder. Use when a module's *.use-case.spec.ts files repeat the same mock-repository literal, inline entity construction, or hardcoded UUIDs across files.

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

Analyze Cursor Bugbot PR comments through a root-cause lens: is the finding valid, and is the suggested fix the real fix or a bandaid over a deeper problem? Use when the user asks to check, assess, or triage bugbot comments.

日本語の概要は準備中です。原文の説明を表示しています。

ayunis-core/ayunis-core342026年10月26日 更新

ayunis-core のスキルをすべて見る

このスキルの問題を報告する