import { MigrationInterface, QueryRunner } from 'typeorm' /** * `twin_instances.model` → `twin_instances.model`. * * ── 왜 개명하나 ──────────────────────────────────────────────────────────────── * 이 컬럼이 담는 것은 커널이 `TwinModelDef` 라 부르는 **트윈 모델**이다. `board` 는 저장 위치의 옛 * 이름이고, 이 앱에는 **진짜 board 가 따로 있다**(things-scene 보드 — 공간 표현의 `boardId`). 같은 * 낱말이 두 가지를 뜻하니 읽는 사람이 매번 어느 쪽인지 판단해야 했고, 코드와 주석이 "board(마스터 * 청사진)" 처럼 번역을 달아 설명해 왔다. 커널이 이미 옳은 이름을 갖고 있으므로 발명할 이름도 없다. * * ── 데이터를 잃지 않는다 ────────────────────────────────────────────────────── * `renameColumn` 은 값을 그대로 둔 채 이름만 바꾼다. 지우고 다시 만들면(엔티티 변경 + synchronize) * 기존 트윈의 모델이 통째로 사라지고, 원천이 없는 트윈은 되살릴 방법이 없다. * * `renameColumn` API 만 쓰므로 지원 대상 5개 드라이버가 각자의 DDL 로 처리한다(raw SQL 금지 규약). * * ── 멱등 ────────────────────────────────────────────────────────────────────── * 이미 `model` 이 있으면(엔티티 선언 + synchronize 가 먼저 지나간 경우) 아무것도 하지 않는다. * 그 경우 옛 컬럼이 남아 있을 수 있는데 **지우지 않는다** — 값이 든 컬럼을 마이그레이션이 알리지 않고 * 버리면 안 된다. 남은 컬럼의 처분은 사람이 확인한 뒤의 일이다. */ const TABLE_NAME = 'twin_instances' const OLD = 'board' const NEW = 'model' export class RenameTwinInstanceBoardToModel1786000000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { const table = await queryRunner.getTable(TABLE_NAME) if (!table) return const has = (name: string) => table.columns.some(c => c.name === name) if (has(NEW) || !has(OLD)) return await queryRunner.renameColumn(table, OLD, NEW) } public async down(queryRunner: QueryRunner): Promise { const table = await queryRunner.getTable(TABLE_NAME) if (!table) return const has = (name: string) => table.columns.some(c => c.name === name) if (has(OLD) || !has(NEW)) return await queryRunner.renameColumn(table, NEW, OLD) } }