import { MigrationInterface, QueryRunner } from 'typeorm' /** * `twin_references.adapter_type` — `operato-mes` → `operato-plant`. * * ── 왜 마이그레이션이 필요한가 ──────────────────────────────────────────────── * 커넥터의 `type` 은 **저장되는 식별자**다. 트윈을 원본에 붙일 때 그 문자열이 이 컬럼에 적히고, * 넘길 때·라이브를 열 때 그 값으로 커넥터를 찾는다(§`getAdapter`). * * 그래서 제품 개명(`operato-mes` → `operato-plant`)이 코드만 바뀌면 **이미 붙어 있는 원본이 커넥터를 * 못 찾는다.** 그때 나오는 것은 이렇다. * * 조치 넘김 `no-adapter` 로 거절 * 라이브 커넥터가 없어 관측이 끊긴다 * 화면 「등록되지 않은 커넥터입니다 (operato-mes)」 한 줄 * * **오류는 안 나고, 원인이 개명이라는 것이 그 문장에 없다.** 트윈은 그대로 서 있고 값만 안 온다. * 이 저장소에서 개명이 저장된 식별자에 닿았을 때 늘 이 모양으로 났다(보드 키·씬 컴포넌트 타입). * * ── 왜 이 패키지인가 ───────────────────────────────────────────────────────── * 표를 든 쪽이 이 패키지다(`twin_references`). 커넥터는 `operato-twin` 이 등록하지만, 그 값이 사는 * 자리는 여기다. 마이그레이션은 표를 든 패키지에 둔다. * * ── 되돌리기 ───────────────────────────────────────────────────────────────── * `down` 이 값을 되돌린다. 옛 코드로 되돌아가는 경우가 실제로 있고(배포 롤백), 그때 값이 새 이름으로 * 남아 있으면 같은 결함이 반대 방향으로 난다. * * 멱등: 해당하는 행이 없으면 아무것도 하지 않는다. TypeORM 질의 빌더만 쓴다 — 드라이버마다 파라미터 * 표기가 다르므로 raw SQL 을 쓰지 않는다. */ const REFS = 'twin_references' const COLUMN = 'adapter_type' /** * 질의 빌더에는 **속성 이름**을 준다. * * 처음에 컬럼 이름(`adapter_type`)으로 썼더니 TypeORM 이 표 이름을 엔티티(`TwinReference`)로 풀고 * 「그런 속성이 없다」로 거절했다 — 표 이름을 주더라도 매핑은 엔티티 기준이다. 컬럼 이름은 표가 * 있는지 볼 때만 쓴다. */ const PROPERTY = 'adapterType' const OLD = 'operato-mes' const NEW = 'operato-plant' async function rename(queryRunner: QueryRunner, from: string, to: string): Promise { /* 표가 아직 없는 배포(첫 기동)에서는 할 일이 없다. */ const table = await queryRunner.getTable(REFS) if (!table?.columns.some(c => c.name === COLUMN)) return /* 객체 형태로 준다 — 문자열 조건은 드라이버마다 식별자 인용이 달라 그대로 나간다. */ await queryRunner.manager .createQueryBuilder() .update(REFS) .set({ [PROPERTY]: to }) .where({ [PROPERTY]: from }) .execute() } export class RenameOperatoMesAdapterType1786600000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { await rename(queryRunner, OLD, NEW) } public async down(queryRunner: QueryRunner): Promise { await rename(queryRunner, NEW, OLD) } }