sonamu 0.5.5 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/entity/migrator.ts"],"sourcesContent":["import _ from \"lodash\";\nimport knex, { Knex } from \"knex\";\nimport prettier from \"prettier\";\nimport chalk from \"chalk\";\nimport { DateTime } from \"luxon\";\nimport { mkdir, readdir, unlink, writeFile } from \"fs/promises\";\nimport { exists } from \"../utils/fs-utils\";\nimport equal from \"fast-deep-equal\";\nimport inflection from \"inflection\";\nimport prompts from \"prompts\";\nimport { execSync } from \"child_process\";\nimport path from \"path\";\n\nimport {\n GenMigrationCode,\n isBelongsToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n isOneToOneRelationProp,\n isRelationProp,\n isVirtualProp,\n isStringProp,\n KnexColumnType,\n MigrationColumn,\n MigrationForeign,\n MigrationIndex,\n MigrationJoinTable,\n MigrationSet,\n MigrationSetAndJoinTable,\n isDecimalProp,\n isFloatProp,\n isTextProp,\n isEnumProp,\n isIntegerProp,\n isKnexError,\n RelationOn,\n} from \"../types/types\";\nimport { EntityManager } from \"./entity-manager\";\nimport { Entity } from \"./entity\";\nimport { Sonamu } from \"../api\";\nimport { ServiceUnavailableException } from \"../exceptions/so-exceptions\";\n\ntype MigratorMode = \"dev\" | \"deploy\";\nexport type MigratorOptions = {\n readonly mode: MigratorMode;\n};\ntype MigrationCode = {\n name: string;\n path: string;\n};\ntype ConnString = `${\"mysql2\"}://${string}@${string}:${number}/${string}`; // mysql2://account@host:port/database\nexport type MigrationStatus = {\n codes: MigrationCode[];\n conns: {\n name: string;\n connKey: string;\n connString: ConnString;\n currentVersion: string;\n status: string | number;\n pending: string[];\n }[];\n preparedCodes: GenMigrationCode[];\n};\n\nexport class Migrator {\n readonly mode: MigratorMode;\n\n targets: {\n compare?: Knex;\n pending: Knex;\n shadow: Knex;\n apply: Knex[];\n };\n\n constructor(options: MigratorOptions) {\n this.mode = options.mode;\n const { dbConfig } = Sonamu;\n\n if (this.mode === \"dev\") {\n const devDB = knex(dbConfig.development_master);\n const testDB = knex(dbConfig.test);\n const fixtureLocalDB = knex(dbConfig.fixture_local);\n\n const applyDBs = [devDB, testDB, fixtureLocalDB];\n if (\n (dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)\n .host !==\n (dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)\n .host ||\n (dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)\n .database !==\n (dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig)\n .database\n ) {\n const fixtureRemoteDB = knex(dbConfig.fixture_remote);\n applyDBs.push(fixtureRemoteDB);\n }\n\n this.targets = {\n compare: devDB,\n pending: devDB,\n shadow: testDB,\n apply: applyDBs,\n };\n } else if (this.mode === \"deploy\") {\n const productionDB = knex(dbConfig.production_master);\n const testDB = knex(dbConfig.test);\n\n this.targets = {\n pending: productionDB,\n shadow: testDB,\n apply: [productionDB],\n };\n } else {\n throw new Error(`잘못된 모드 ${this.mode} 입력`);\n }\n }\n\n async getMigrationCodes(): Promise<{\n normal: MigrationCode[];\n onlyTs: MigrationCode[];\n onlyJs: MigrationCode[];\n }> {\n const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;\n\n if (!(await exists(srcMigrationsDir))) {\n await mkdir(srcMigrationsDir, {\n recursive: true,\n });\n }\n if (!(await exists(distMigrationsDir))) {\n await mkdir(distMigrationsDir, {\n recursive: true,\n });\n }\n const srcMigrations = (await readdir(srcMigrationsDir))\n .filter((f) => f.endsWith(\".ts\"))\n .map((f) => f.split(\".\")[0]);\n const distMigrations = (await readdir(distMigrationsDir))\n .filter((f) => f.endsWith(\".js\"))\n .map((f) => f.split(\".\")[0]);\n\n const normal = _.intersection(srcMigrations, distMigrations)\n .map((filename) => {\n return {\n name: filename,\n path: path.join(srcMigrationsDir, filename) + \".ts\",\n };\n })\n .sort((a, b) => (a > b ? 1 : -1));\n\n const onlyTs = _.difference(srcMigrations, distMigrations).map(\n (filename) => {\n return {\n name: filename,\n path: path.join(srcMigrationsDir, filename) + \".ts\",\n };\n }\n );\n\n const onlyJs = _.difference(distMigrations, srcMigrations).map(\n (filename) => {\n return {\n name: filename,\n path: path.join(distMigrationsDir, filename) + \".js\",\n };\n }\n );\n\n return {\n normal,\n onlyTs,\n onlyJs,\n };\n }\n\n async getStatus(): Promise<MigrationStatus> {\n const { normal, onlyTs, onlyJs } = await this.getMigrationCodes();\n if (onlyTs.length > 0) {\n console.debug({ onlyTs });\n throw new ServiceUnavailableException(\n `There are un-compiled TS migration files.\\nPlease compile them first.\\n\\n${onlyTs\n .map((f) => f.name)\n .join(\"\\n\")}`\n );\n }\n if (onlyJs.length > 0) {\n console.debug({ onlyJs });\n await Promise.all(\n onlyJs.map(async (f) => {\n execSync(\n `rm -f ${f.path.replace(\"/src/\", \"/dist/\").replace(\".ts\", \".js\")}`\n );\n })\n );\n }\n\n const connKeys = Object.keys(Sonamu.dbConfig).filter(\n (key) => key.endsWith(\"_slave\") === false\n ) as (keyof typeof Sonamu.dbConfig)[];\n\n const statuses = await Promise.all(\n connKeys.map(async (connKey) => {\n const knexOptions = Sonamu.dbConfig[connKey];\n const tConn = knex(knexOptions);\n\n const status = await (async () => {\n try {\n return await tConn.migrate.status();\n } catch (err) {\n console.warn(chalk.yellow(`${connKey}의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\\n시도한 연결 설정:\\n${JSON.stringify(knexOptions.connection, null, 2)}\\n발생한 에러:\\n${err}\\n`));\n return 'error'/*클라이언트에서 에러 체크에 사용하는 리터럴입니다.*/;\n }\n })();\n const pending = await (async () => {\n try {\n const [, fdList] = await tConn.migrate.list();\n return fdList.map((fd: { file: string }) =>\n fd.file.replace(\".js\", \"\")\n );\n } catch (err) {\n return [];\n }\n })();\n const currentVersion = await (async () => {\n try {\n return await tConn.migrate.currentVersion();\n } catch (err) {\n return 'error';\n }\n })();\n\n const connection =\n knexOptions.connection as Knex.MySql2ConnectionConfig;\n\n await tConn.destroy();\n\n return {\n name: connKey.replace(\"_master\", \"\"),\n connKey,\n connString: `mysql2://${connection.user ?? \"\"}@${connection.host}:${\n connection.port\n }/${connection.database}` as ConnString,\n currentVersion,\n status,\n pending,\n };\n })\n );\n\n const preparedCodes: GenMigrationCode[] = await (async () => {\n const status0conn = statuses.find((status) => status.status === 0);\n if (status0conn === undefined) {\n return [];\n }\n\n const compareDBconn = knex(Sonamu.dbConfig[status0conn.connKey]);\n const genCodes = await this.compareMigrations(compareDBconn);\n\n await compareDBconn.destroy();\n\n return genCodes;\n })();\n\n return {\n conns: statuses,\n codes: normal,\n preparedCodes,\n };\n /*\n TS/JS 코드 컴파일 상태 확인\n 1. 원본 파일 없는 JS파일이 존재하는 경우: 삭제\n 2. 컴파일 되지 않은 TS파일이 존재하는 경우: throw 쳐서 데브 서버 오픈 요청\n \n DB 마이그레이션 상태 확인\n 1. 전체 DB설정에 대해서 현재 마이그레이션 상태 확인\n - connKey: string\n - status: number\n - currentVersion: string\n - list: { file: string; directory: string }[]\n \n */\n }\n\n async runAction(\n action: \"latest\" | \"rollback\",\n targets: string[]\n ): Promise<\n {\n connKey: string;\n batchNo: number;\n applied: string[];\n }[]\n > {\n // get uniq knex configs\n const configs = _.uniqBy(\n targets\n .map((target) => ({\n connKey: target,\n options: Sonamu.dbConfig[target as keyof typeof Sonamu.dbConfig],\n }))\n .filter((c) => c.options !== undefined),\n ({ options }) =>\n `${(options.connection as Knex.MySql2ConnectionConfig).host}:${\n (options.connection as Knex.MySql2ConnectionConfig).port ?? 3306\n }/${(options.connection as Knex.MySql2ConnectionConfig).database}`\n );\n\n // get connections\n const conns = await Promise.all(\n configs.map(async (config) => ({\n connKey: config.connKey,\n knex: knex(config.options),\n }))\n );\n\n // action\n const result = await (async () => {\n switch (action) {\n case \"latest\":\n return Promise.all(\n conns.map(async ({ connKey, knex }) => {\n const [batchNo, applied] = await knex.migrate.latest();\n return {\n connKey,\n batchNo,\n applied,\n };\n })\n );\n case \"rollback\":\n return Promise.all(\n conns.map(async ({ connKey, knex }) => {\n const [batchNo, applied] = await knex.migrate.rollback();\n return {\n connKey,\n batchNo,\n applied,\n };\n })\n );\n }\n })();\n\n // destroy\n await Promise.all(\n conns.map(({ knex }) => {\n return knex.destroy();\n })\n );\n\n return result;\n }\n\n async delCodes(codeNames: string[]): Promise<number> {\n const { conns } = await this.getStatus();\n if (\n conns.some((conn) => {\n return codeNames.some(\n (codeName) => conn.pending.includes(codeName) === false\n );\n })\n ) {\n throw new Error(\n \"You cannot delete a migration file if there is already applied.\"\n );\n }\n\n const delFiles = codeNames\n .map((codeName) => [\n `${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`,\n `${Sonamu.apiRootPath}/dist/migrations/${codeName}.js`,\n ])\n .flat();\n\n const res = await Promise.all(\n delFiles.map(async (delFile) => {\n if (await exists(delFile)) {\n console.log(chalk.red(`DELETE: ${delFile}`));\n await unlink(delFile);\n return delFiles.includes(\".ts\") ? 1 : 0;\n }\n return 0;\n })\n );\n return _.sum(res);\n }\n\n async generatePreparedCodes(): Promise<number> {\n const { preparedCodes } = await this.getStatus();\n if (preparedCodes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return 0;\n }\n\n // 실제 코드 생성\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n\n for (const [index, pcode] of preparedCodes.entries()) {\n if (pcode.formatted) {\n const dateTag = DateTime.local()\n .plus({ seconds: index })\n .toFormat(\"yyyyMMddHHmmss\");\n const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;\n await writeFile(filePath, pcode.formatted!);\n console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));\n }\n }\n\n return preparedCodes.length;\n }\n\n async clearPendingList(): Promise<void> {\n const [, pendingList] = (await this.targets.pending.migrate.list()) as [\n unknown,\n {\n file: string;\n directory: string;\n }[],\n ];\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n const delList = pendingList.map((df) => {\n return path.join(migrationsDir, df.file).replace(\".js\", \".ts\");\n });\n for (let p of delList) {\n if (await exists(p)) {\n await unlink(p);\n }\n }\n await this.cleanUpDist(true);\n }\n\n async check(): Promise<void> {\n const codes = await this.compareMigrations(this.targets.compare!);\n if (codes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return;\n }\n\n // 현재 생성된 코드 표기\n console.table(codes, [\"type\", \"title\"]);\n console.log(codes[0]);\n }\n\n async run(): Promise<void> {\n // pending 마이그레이션 확인\n const [, pendingList] = await this.targets.pending.migrate.list();\n if (pendingList.length > 0) {\n console.log(\n chalk.red(\"pending 된 마이그레이션이 존재합니다.\"),\n pendingList.map((pending: any) => pending.file)\n );\n\n // pending이 있는 경우 Shadow DB 테스트 진행 여부 컨펌\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"Shadow DB 테스트를 진행하시겠습니까?\",\n initial: true,\n });\n if (answer.value === false) {\n return;\n }\n\n console.time(chalk.blue(\"Migrator - runShadowTest\"));\n await this.runShadowTest();\n console.timeEnd(chalk.blue(\"Migrator - runShadowTest\"));\n await Promise.all(\n this.targets.apply.map(async (applyDb) => {\n const label = chalk.green(\n `APPLIED ${\n applyDb.client.connectionSettings.host\n } ${applyDb.client.database()}`\n );\n console.time(label);\n const [,] = await applyDb.migrate.latest();\n console.timeEnd(label);\n })\n );\n }\n\n // Entity-DB간 비교하여 코드 생성 리턴\n const codes = await this.compareMigrations(this.targets.compare!);\n if (codes.length === 0) {\n console.log(chalk.green(\"\\n현재 모두 싱크된 상태입니다.\"));\n return;\n }\n\n // 현재 생성된 코드 표기\n console.table(codes, [\"type\", \"title\"]);\n\n /* DEBUG: 디버깅용 코드\n codes.map((code) => console.log(code.formatted));\n process.exit();\n */\n\n // 실제 파일 생성 프롬프트\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"마이그레이션 코드를 생성하시겠습니까?\",\n initial: false,\n });\n if (answer.value === false) {\n return;\n }\n\n // 실제 코드 생성\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n\n for (const [index, code] of codes.entries()) {\n if (code.formatted) {\n const dateTag = DateTime.local()\n .plus({ seconds: index })\n .toFormat(\"yyyyMMddHHmmss\");\n const filePath = `${migrationsDir}/${dateTag}_${code.title}.ts`;\n await writeFile(filePath, code.formatted!);\n console.log(chalk.green(`MIGRTAION CREATED ${filePath}`));\n }\n }\n }\n\n async rollback() {\n console.time(chalk.red(\"rollback:\"));\n const rollbackAllResult = await Promise.all(\n this.targets.apply.map(async (db) => {\n await db.migrate.forceFreeMigrationsLock();\n return db.migrate.rollback(undefined, false);\n })\n );\n console.dir({ rollbackAllResult }, { depth: null });\n console.timeEnd(chalk.red(\"rollback:\"));\n }\n\n async cleanUpDist(force: boolean = false): Promise<void> {\n async function getFilesUnder(dir: string): Promise<string[]> {\n const migrationPath = path.join(Sonamu.apiRootPath, dir, \"migrations\");\n if (!(await exists(migrationPath))) {\n await mkdir(migrationPath, {\n recursive: true,\n });\n }\n return (await readdir(migrationPath)).filter(\n (filename) => filename.startsWith(\".\") === false\n );\n }\n\n const files = {\n src: await getFilesUnder(\"src\"),\n dist: await getFilesUnder(\"dist\"),\n };\n\n const diffOnSrc = _.differenceBy(\n files.src,\n files.dist,\n (filename) => filename.split(\".\")[0]\n );\n if (diffOnSrc.length > 0) {\n throw new Error(\n \"컴파일 되지 않은 파일이 있습니다.\\n\" + diffOnSrc.join(\"\\n\")\n );\n }\n\n const diffOnDist = _.differenceBy(\n files.dist,\n files.src,\n (filename) => filename.split(\".\")[0]\n );\n if (diffOnDist.length > 0) {\n console.log(chalk.red(\"원본 ts파일을 찾을 수 없는 js파일이 있습니다.\"));\n console.log(diffOnDist);\n\n if (!force) {\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"삭제를 진행하시겠습니까?\",\n initial: true,\n });\n if (answer.value === false) {\n return;\n }\n }\n\n const filesToRm = diffOnDist.map((filename) => {\n return path.join(Sonamu.apiRootPath, \"dist\", \"migrations\", filename);\n });\n for (const filePath of filesToRm) {\n await unlink(filePath);\n }\n console.log(chalk.green(`${filesToRm.length}건 삭제되었습니다!`));\n }\n }\n\n async runShadowTest(): Promise<\n {\n connKey: string;\n batchNo: number;\n applied: string[];\n }[]\n > {\n // ShadowDB 생성 후 테스트 진행\n const tdb = knex(Sonamu.dbConfig.test);\n const tdbConn = Sonamu.dbConfig.test.connection as Knex.MySql2ConnectionConfig;\n const shadowDatabase = tdbConn.database + \"__migration_shadow\";\n const tmpSqlPath = `/tmp/${shadowDatabase}.sql`;\n\n // 테스트DB 덤프 후 Database명 치환\n console.log(\n chalk.magenta(`${tdbConn.database}의 데이터 ${tmpSqlPath}로 덤프`)\n );\n execSync(\n `mysqldump -h${tdbConn.host} -P${tdbConn.port ?? 3306} -u${tdbConn.user} -p'${tdbConn.password}' ${tdbConn.database} --single-transaction --no-create-db --triggers > ${tmpSqlPath};`\n );\n execSync(\n `sed -i'' -e 's/\\`${tdbConn.database}\\`/\\`${shadowDatabase}\\`/g' ${tmpSqlPath};`\n );\n\n // 기존 ShadowDB 리셋\n console.log(chalk.magenta(`${shadowDatabase} 리셋`));\n await tdb.raw(`DROP DATABASE IF EXISTS \\`${shadowDatabase}\\`;`);\n await tdb.raw(`CREATE DATABASE \\`${shadowDatabase}\\`;`);\n\n // ShadowDB 테이블 + 데이터 생성\n console.log(chalk.magenta(`${shadowDatabase} 데이터베이스 생성`));\n execSync(\n `mysql -h${tdbConn.host} -P${tdbConn.port ?? 3306} -u${tdbConn.user} -p'${tdbConn.password}' ${shadowDatabase} < ${tmpSqlPath};`\n );\n\n // shadow db 테스트 진행\n const sdb = knex({\n ...Sonamu.dbConfig.test,\n connection: {\n ...tdbConn,\n database: shadowDatabase,\n password: tdbConn.password,\n },\n });\n\n // shadow db 테스트 진행\n try {\n const [batchNo, applied] = await sdb.migrate.latest();\n console.log(chalk.green(\"Shadow DB 테스트에 성공했습니다!\"), {\n batchNo,\n applied,\n });\n\n // 생성한 Shadow DB 삭제\n console.log(chalk.magenta(`${shadowDatabase} 삭제`));\n await tdb.raw(`DROP DATABASE IF EXISTS \\`${shadowDatabase}\\`;`);\n\n return [\n {\n connKey: \"shadow\",\n batchNo,\n applied,\n },\n ];\n } catch (e) {\n console.error(e);\n throw new ServiceUnavailableException(\"Shadow DB 테스트 진행 중 에러\");\n } finally {\n await tdb.destroy();\n }\n }\n\n async resetAll() {\n const answer = await prompts({\n type: \"confirm\",\n name: \"value\",\n message: \"모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제하시겠습니까?\",\n initial: false,\n });\n if (answer.value === false) {\n return;\n }\n\n console.time(chalk.red(\"rollback-all:\"));\n const rollbackAllResult = await Promise.all(\n this.targets.apply.map(async (db) => {\n await db.migrate.forceFreeMigrationsLock();\n return db.migrate.rollback(undefined, true);\n })\n );\n console.log({ rollbackAllResult });\n console.timeEnd(chalk.red(\"rollback-all:\"));\n\n const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;\n console.time(chalk.red(\"delete migration files\"));\n execSync(`rm -f ${migrationsDir}/*`);\n execSync(`rm -f ${migrationsDir.replace(\"/src/\", \"/dist/\")}/*`);\n console.timeEnd(chalk.red(\"delete migration files\"));\n }\n\n async compareMigrations(compareDB: Knex): Promise<GenMigrationCode[]> {\n // Entity 순회하여 싱크\n const entityIds = EntityManager.getAllIds();\n\n // 조인테이블 포함하여 Entity에서 MigrationSet 추출\n const entitySetsWithJoinTable = entityIds\n .filter((entityId) => {\n const entity = EntityManager.get(entityId);\n return entity.props.length > 0;\n })\n .map((entityId) => {\n const entity = EntityManager.get(entityId);\n return this.getMigrationSetFromEntity(entity);\n });\n\n // 조인테이블만 추출\n const joinTablesWithDup = entitySetsWithJoinTable\n .map((entitySet) => entitySet.joinTables)\n .flat();\n // 중복 제거 (중복인 경우 indexes를 병합)\n const joinTables = Object.values(\n _.groupBy(joinTablesWithDup, (jt) => jt.table)\n ).map((tables) => {\n if (tables.length === 1) {\n return tables[0];\n }\n return {\n ...tables[0],\n indexes: _.uniqBy(\n tables.flatMap((t) => t.indexes),\n (index) => [index.type, ...index.columns.sort()].join(\"-\")\n ),\n };\n });\n\n // 조인테이블 포함하여 MigrationSet 배열\n const entitySets: MigrationSet[] = [\n ...entitySetsWithJoinTable,\n ...joinTables,\n ];\n\n const codes: GenMigrationCode[] = (\n await Promise.all(\n entitySets.map(async (entitySet) => {\n const dbSet = await this.getMigrationSetFromDB(\n compareDB,\n entitySet.table\n );\n if (dbSet === null) {\n // 기존 테이블 없음, 새로 테이블 생성\n return [\n await this.generateCreateCode_ColumnAndIndexes(\n entitySet.table,\n entitySet.columns,\n entitySet.indexes\n ),\n ...(await this.generateCreateCode_Foreign(\n entitySet.table,\n entitySet.foreigns\n )),\n ];\n }\n\n // 기존 테이블 존재하는 케이스\n const replaceColumnDefaultTo = (col: MigrationColumn) => {\n // float인 경우 기본값을 0으로 지정하는 경우 \"0.00\"으로 변환되는 케이스 대응\n if (\n col.type === \"float\" &&\n col.defaultTo &&\n String(col.defaultTo).includes('\"') === false\n ) {\n col.defaultTo = `\"${Number(col.defaultTo).toFixed(\n col.scale ?? 2\n )}\"`;\n }\n // string인 경우 기본값이 빈 스트링인 경우 대응\n if (col.type === \"string\" && col.defaultTo === \"\") {\n col.defaultTo = '\"\"';\n }\n // boolean인 경우 기본값 정규화 (MySQL에서는 TINYINT(1)로 저장되므로 0 또는 1로 정규화)\n // TODO: db.ts에 typeCase 설정 확인하여 처리하도록 수정 필요\n if (col.type === \"boolean\" && col.defaultTo !== undefined) {\n if (col.defaultTo === \"0\" || col.defaultTo === \"false\") {\n col.defaultTo = \"0\";\n } else if (col.defaultTo === \"1\" || col.defaultTo === \"true\") {\n col.defaultTo = \"1\";\n }\n }\n return col;\n };\n const entityColumns = _.sortBy(entitySet.columns, (a) => a.name).map(\n replaceColumnDefaultTo\n );\n const dbColumns = _.sortBy(dbSet.columns, (a) => a.name).map(\n replaceColumnDefaultTo\n );\n\n /* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인\n const entityColumn = entitySet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n const dbColumn = dbSet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n console.debug({ entityColumn, dbColumn });\n */\n\n const entityIndexes = _.sortBy(entitySet.indexes, (a) =>\n [a.type, ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1))].join(\n \"-\"\n )\n );\n const dbIndexes = _.sortBy(dbSet.indexes, (a) =>\n [a.type, ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1))].join(\n \"-\"\n )\n );\n\n const replaceNoActionOnMySQL = (f: MigrationForeign) => {\n // MySQL에서 RESTRICT와 NO ACTION은 동일함\n const { onDelete, onUpdate } = f;\n return {\n ...f,\n onUpdate: onUpdate === \"RESTRICT\" ? \"NO ACTION\" : onUpdate,\n onDelete: onDelete === \"RESTRICT\" ? \"NO ACTION\" : onDelete,\n };\n };\n\n const entityForeigns = _.sortBy(entitySet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n const dbForeigns = _.sortBy(dbSet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n\n // 삭제될 컬럼 목록 계산\n const droppingColumns = _.differenceBy(\n dbColumns,\n entityColumns,\n (col) => col.name\n );\n\n const alterCodes: (GenMigrationCode | GenMigrationCode[] | null)[] =\n [];\n\n // 1. columnsAndIndexes 처리\n const isEqualColumns = equal(entityColumns, dbColumns);\n const isEqualIndexes = equal(\n entityIndexes.map((index) => _.omit(index, [\"parser\"])),\n dbIndexes\n );\n if (!isEqualColumns || !isEqualIndexes) {\n alterCodes.push(\n await this.generateAlterCode_ColumnAndIndexes(\n entitySet.table,\n entityColumns,\n entityIndexes,\n dbColumns,\n dbIndexes,\n dbSet.foreigns\n )\n );\n }\n\n // 2. foreigns 처리 (삭제될 컬럼 정보 전달)\n if (equal(entityForeigns, dbForeigns) === false) {\n alterCodes.push(\n await this.generateAlterCode_Foreigns(\n entitySet.table,\n entityForeigns,\n dbForeigns,\n droppingColumns\n )\n );\n }\n\n if (alterCodes.every((alterCode) => alterCode === null)) {\n return null;\n } else {\n return alterCodes.filter((alterCode) => alterCode !== null).flat();\n }\n })\n )\n )\n .flat()\n .filter((code) => code !== null) as GenMigrationCode[];\n\n /*\n normal 타입이 앞으로, foreign 이 뒤로\n */\n codes.sort((codeA, codeB) => {\n if (codeA.type === \"foreign\" && codeB.type == \"normal\") {\n return 1;\n } else if (codeA.type === \"normal\" && codeB.type === \"foreign\") {\n return -1;\n } else {\n return 0;\n }\n });\n\n return codes;\n }\n\n /*\n 기존 테이블 정보 읽어서 MigrationSet 형식으로 리턴\n */\n async getMigrationSetFromDB(\n compareDB: Knex,\n table: string\n ): Promise<MigrationSet | null> {\n let dbColumns: DBColumn[], dbIndexes: DBIndex[], dbForeigns: DBForeign[];\n try {\n [dbColumns, dbIndexes, dbForeigns] = await this.readTable(\n compareDB,\n table\n );\n } catch (e: unknown) {\n if (isKnexError(e) && e.code === \"ER_NO_SUCH_TABLE\") {\n return null;\n }\n console.error(e);\n return null;\n }\n\n const columns: MigrationColumn[] = dbColumns.map((dbColumn) => {\n const dbColType = this.resolveDBColType(dbColumn.Type, dbColumn.Field);\n return {\n name: dbColumn.Field,\n nullable: dbColumn.Null !== \"NO\",\n ...dbColType,\n ...(() => {\n if (dbColumn.Default !== null) {\n return {\n defaultTo: dbColumn.Default,\n };\n }\n return {};\n })(),\n };\n });\n\n const dbIndexesGroup = _.groupBy(\n dbIndexes.filter(\n (dbIndex) =>\n dbIndex.Key_name !== \"PRIMARY\" &&\n !dbForeigns.find(\n (dbForeign) => dbForeign.keyName === dbIndex.Key_name\n )\n ),\n (dbIndex) => dbIndex.Key_name\n );\n\n const parseIndexType = (index: DBIndex) => {\n if (index.Index_type === \"FULLTEXT\") {\n return \"fulltext\";\n }\n return index.Non_unique === 1 ? \"index\" : \"unique\";\n };\n\n // indexes 처리\n const indexes: MigrationIndex[] = Object.keys(dbIndexesGroup).map(\n (keyName) => {\n const currentIndexes = dbIndexesGroup[keyName];\n return {\n type: parseIndexType(currentIndexes[0]),\n columns: currentIndexes.map(\n (currentIndex) => currentIndex.Column_name\n ),\n };\n }\n );\n // console.log(table);\n // console.table(dbIndexes);\n // console.table(dbForeigns);\n\n // foreigns 처리\n const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {\n return {\n columns: [dbForeign.from],\n to: `${dbForeign.referencesTable}.${dbForeign.referencesField}`,\n onUpdate: dbForeign.onUpdate as RelationOn,\n onDelete: dbForeign.onDelete as RelationOn,\n };\n });\n\n return {\n table,\n columns,\n indexes,\n foreigns,\n };\n }\n\n resolveDBColType(\n colType: string,\n colField: string\n ): Pick<\n MigrationColumn,\n \"type\" | \"unsigned\" | \"length\" | \"precision\" | \"scale\"\n > {\n let [rawType, unsigned] = colType.split(\" \");\n const matched = rawType.match(/\\(([0-9]+)\\)/);\n let length;\n if (matched !== null && matched[1]) {\n rawType = rawType.replace(/\\(([0-9]+)\\)/, \"\");\n length = parseInt(matched[1]);\n }\n\n if (rawType === \"char\" && colField === \"uuid\") {\n return {\n type: \"uuid\",\n };\n }\n\n switch (rawType) {\n case \"int\":\n return {\n type: \"integer\",\n unsigned: unsigned === \"unsigned\",\n };\n case \"varchar\":\n // case \"char\":\n return {\n type: \"string\",\n ...(length !== undefined && {\n length,\n }),\n };\n case \"text\":\n case \"mediumtext\":\n case \"longtext\":\n case \"timestamp\":\n case \"json\":\n case \"date\":\n case \"time\":\n return {\n type: rawType,\n };\n case \"datetime\":\n return {\n type: \"datetime\",\n };\n case \"tinyint\":\n return {\n type: \"boolean\",\n };\n default:\n // decimal 처리\n if (rawType.startsWith(\"decimal\")) {\n const [, precision, scale] =\n rawType.match(/decimal\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"decimal\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n } else if (rawType.startsWith(\"float\")) {\n const [, precision, scale] =\n rawType.match(/float\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"float\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n }\n throw new Error(`resolve 불가능한 DB컬럼 타입 ${colType} ${rawType}`);\n }\n }\n\n /*\n 기존 테이블 읽어서 cols, indexes 반환\n */\n async readTable(\n compareDB: Knex,\n tableName: string\n ): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {\n // 테이블 정보\n try {\n const [_cols] = (await compareDB.raw(\n `SHOW FIELDS FROM ${tableName}`\n )) as [DBColumn[]];\n const cols = _cols.map((col) => ({\n ...col,\n // Default 값은 숫자나 MySQL Expression이 아닌 경우 \"\"로 감싸줌\n ...(col.Default !== null && {\n Default:\n col.Default.replace(/[0-9]+/g, \"\").length > 0 &&\n col.Extra !== \"DEFAULT_GENERATED\"\n ? `\"${col.Default}\"`\n : col.Default,\n }),\n }));\n\n const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);\n const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);\n const ddl = row[\"Create Table\"];\n const matched = ddl.match(/CONSTRAINT .+/g);\n const foreignKeys = (matched ?? []).map((line: string) => {\n // 해당 라인을 정규식으로 파싱\n const matched = line.match(\n /CONSTRAINT `(.+)` FOREIGN KEY \\(`(.+)`\\) REFERENCES `(.+)` \\(`(.+)`\\)( ON [A-Z ]+)*/\n );\n if (!matched) {\n throw new Error(`인식할 수 없는 FOREIGN KEY CONSTRAINT ${line}`);\n }\n const [, keyName, from, referencesTable, referencesField, onClause] =\n matched;\n // console.debug({ tableName, line, onClause });\n\n const [onUpdateFull, _onUpdate] =\n (onClause ?? \"\").match(/ON UPDATE ([A-Z ]+)$/) ?? [];\n const onUpdate = _onUpdate ?? \"NO ACTION\";\n\n const onDelete =\n (onClause ?? \"\")\n .replace(onUpdateFull ?? \"\", \"\")\n .match(/ON DELETE ([A-Z ]+)/)?.[1]\n ?.trim() ?? \"NO ACTION\";\n\n return {\n keyName,\n from,\n referencesTable,\n referencesField,\n onDelete,\n onUpdate,\n };\n });\n return [cols, indexes, foreignKeys];\n } catch (e) {\n throw e;\n }\n }\n\n /*\n Entity 내용 읽어서 MigrationSetAndJoinTable 추출\n */\n getMigrationSetFromEntity(entity: Entity): MigrationSetAndJoinTable {\n const migrationSet: MigrationSetAndJoinTable = entity.props.reduce(\n (r, prop) => {\n // virtual 필드 제외\n if (isVirtualProp(prop)) {\n return r;\n }\n // HasMany 케이스는 아무 처리도 하지 않음\n if (isHasManyRelationProp(prop)) {\n return r;\n }\n\n // 일반 컬럼\n if (!isRelationProp(prop)) {\n // type resolve\n let type: KnexColumnType;\n if (isTextProp(prop)) {\n type = prop.textType;\n } else if (isEnumProp(prop)) {\n type = \"string\";\n } else {\n type = prop.type as KnexColumnType;\n }\n\n const column = {\n name: prop.name,\n type,\n ...(isIntegerProp(prop) && { unsigned: prop.unsigned === true }),\n ...((isStringProp(prop) || isEnumProp(prop)) && {\n length: prop.length,\n }),\n nullable: prop.nullable === true,\n ...(() => {\n if (prop.dbDefault !== undefined) {\n return {\n defaultTo: prop.dbDefault,\n };\n }\n return {};\n })(),\n // FIXME: float(N, M) deprecated\n // Decimal, Float 타입의 경우 precision, scale 추가\n ...((isDecimalProp(prop) || isFloatProp(prop)) && {\n precision: prop.precision ?? 8,\n scale: prop.scale ?? 2,\n }),\n };\n\n r.columns.push(column);\n }\n\n if (isManyToManyRelationProp(prop)) {\n // ManyToMany 케이스\n const relMd = EntityManager.get(prop.with);\n const table1 = entity.table;\n const table2 = relMd.table;\n const join = {\n from: `${entity.table}.id`,\n through: {\n from: `${prop.joinTable}.${inflection.singularize(table1)}_id`,\n to: `${prop.joinTable}.${inflection.singularize(table2)}_id`,\n onUpdate: prop.onUpdate,\n onDelete: prop.onDelete,\n },\n to: `${relMd.table}.id`,\n };\n const through = join.through;\n const fields = [through.from, through.to];\n r.joinTables.push({\n table: through.from.split(\".\")[0],\n indexes: [\n {\n type: \"unique\",\n columns: [\"uuid\"],\n },\n // 조인 테이블에 걸린 인덱스 찾아와서 연결\n ...entity.indexes\n .filter((index) =>\n index.columns.find((col) =>\n col.includes(prop.joinTable + \".\")\n )\n )\n .map((index) => ({\n ...index,\n columns: index.columns.map((col) =>\n col.replace(prop.joinTable + \".\", \"\")\n ),\n })),\n ],\n columns: [\n {\n name: \"id\",\n type: \"integer\",\n nullable: false,\n unsigned: true,\n },\n ...fields.map((field) => {\n return {\n name: field.split(\".\")[1],\n type: \"integer\",\n nullable: false,\n unsigned: true,\n } as MigrationColumn;\n }),\n {\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n },\n ],\n foreigns: fields.map((field) => {\n // 현재 필드가 어떤 테이블에 속하는지 판단\n const col = field.split(\".\")[1];\n const to = (() => {\n if (\n inflection.singularize(join.to.split(\".\")[0]) + \"_id\" ===\n col\n ) {\n return join.to;\n } else {\n return join.from;\n }\n })();\n return {\n columns: [col],\n to,\n onUpdate: through.onUpdate,\n onDelete: through.onDelete,\n };\n }),\n });\n return r;\n } else if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n // -OneRelation 케이스\n const idColumnName = prop.name + \"_id\";\n r.columns.push({\n name: idColumnName,\n type: \"integer\",\n unsigned: true,\n nullable: prop.nullable ?? false,\n });\n if ((prop.useConstraint ?? true) === true) {\n r.foreigns.push({\n columns: [idColumnName],\n to: `${inflection\n .underscore(inflection.pluralize(prop.with))\n .toLowerCase()}.id`,\n onUpdate: prop.onUpdate ?? \"RESTRICT\",\n onDelete: prop.onDelete ?? \"RESTRICT\",\n });\n }\n }\n\n return r;\n },\n {\n table: entity.table,\n columns: [] as MigrationColumn[],\n indexes: [] as MigrationIndex[],\n foreigns: [] as MigrationForeign[],\n joinTables: [] as MigrationJoinTable[],\n }\n );\n\n // indexes\n migrationSet.indexes = entity.indexes.filter((index) =>\n index.columns.find((col) => col.includes(\".\") === false)\n );\n\n // uuid\n migrationSet.columns = migrationSet.columns.concat({\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n } as MigrationColumn);\n migrationSet.indexes = migrationSet.indexes.concat({\n type: \"unique\",\n columns: [\"uuid\"],\n } as MigrationIndex);\n\n return migrationSet;\n }\n\n /*\n MigrationColumn[] 읽어서 컬럼 정의하는 구문 생성\n */\n genColumnDefinitions(columns: MigrationColumn[]): string[] {\n return columns.map((column) => {\n const chains: string[] = [];\n if (column.name === \"id\") {\n return `table.increments().primary();`;\n }\n\n // FIXME: float(M,D) deprecated -> decimal(M,D) 이용하도록 하고, float/double 처리 추가\n if (column.type === \"float\" || column.type === \"decimal\") {\n chains.push(\n `${column.type}('${column.name}', ${column.precision}, ${column.scale})`\n );\n } else {\n // type, length\n let columnType = column.type;\n let extraType: string | undefined;\n if (columnType.includes(\"text\") && columnType !== \"text\") {\n extraType = columnType;\n columnType = \"text\";\n }\n chains.push(\n `${column.type}('${column.name}'${\n column.length ? `, ${column.length}` : \"\"\n }${extraType ? `, '${extraType}'` : \"\"})`\n );\n }\n if (column.unsigned) {\n chains.push(\"unsigned()\");\n }\n\n // nullable\n chains.push(column.nullable ? \"nullable()\" : \"notNullable()\");\n\n // defaultTo\n if (column.defaultTo !== undefined) {\n if (\n typeof column.defaultTo === \"string\" &&\n column.defaultTo.startsWith(`\"`)\n ) {\n chains.push(`defaultTo(${column.defaultTo})`);\n } else {\n chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);\n }\n }\n\n return `table.${chains.join(\".\")};`;\n });\n }\n\n /*\n MigrationIndex[] 읽어서 인덱스/유니크 정의하는 구문 생성\n */\n genIndexDefinitions(indexes: MigrationIndex[]): string[] {\n if (indexes.length === 0) {\n return [];\n }\n\n const methodMap = {\n index: \"index\",\n fulltext: \"index\",\n unique: \"unique\",\n };\n\n const lines = _.uniq(\n indexes.reduce((r, index) => {\n r.push(\n `table.${methodMap[index.type]}([${index.columns\n .map((col) => `'${col}'`)\n .join(\",\")}], ${\n index.type === \"fulltext\"\n ? \"undefined, { indexType: 'FULLTEXT' }\"\n : \"\"\n })`\n );\n return r;\n }, [] as string[])\n );\n return lines;\n }\n\n /*\n MigrationForeign[] 읽어서 외부키 constraint 정의하는 구문 생성\n */\n genForeignDefinitions(\n table: string,\n foreigns: MigrationForeign[]\n ): { up: string[]; down: string[] } {\n return foreigns.reduce(\n (r, foreign) => {\n const columnsStringQuote = foreign.columns\n .map((col) => `'${col.replace(`${table}.`, \"\")}'`)\n .join(\",\");\n r.up.push(\n `table.foreign('${foreign.columns.join(\",\")}')\n .references('${foreign.to}')\n .onUpdate('${foreign.onUpdate}')\n .onDelete('${foreign.onDelete}')`\n );\n r.down.push(`table.dropForeign([${columnsStringQuote}])`);\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n }\n\n /*\n 테이블 생성하는 케이스 - 컬럼/인덱스 생성\n */\n async generateCreateCode_ColumnAndIndexes(\n table: string,\n columns: MigrationColumn[],\n indexes: MigrationIndex[]\n ): Promise<GenMigrationCode> {\n // fulltext index 분리\n const [ngramIndexes, standardIndexes] = _.partition(\n indexes,\n (i) => i.type === \"fulltext\" && i.parser === \"ngram\"\n );\n\n // 컬럼, 인덱스 처리\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `await knex.schema.createTable(\"${table}\", (table) => {`,\n \"// columns\",\n ...this.genColumnDefinitions(columns),\n \"\",\n \"// indexes\",\n ...standardIndexes.map((index) => this.genIndexDefinition(index, table)),\n \"});\",\n // ngram은 knex.raw로 처리하므로 createTable 밖에서 실행\n ...ngramIndexes.map((index) => this.genIndexDefinition(index, table)),\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n ` return knex.schema.dropTable(\"${table}\");`,\n \"}\",\n ];\n return {\n table,\n type: \"normal\",\n title: `create__${table}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n };\n }\n\n /*\n 테이블 생성하는 케이스 - FK 생성\n */\n async generateCreateCode_Foreign(\n table: string,\n foreigns: MigrationForeign[]\n ): Promise<GenMigrationCode[]> {\n if (foreigns.length === 0) {\n return [];\n }\n\n const { up, down } = this.genForeignDefinitions(table, foreigns);\n if (up.length === 0 && down.length === 0) {\n console.log(\"fk 가 뭔가 다릅니다\");\n return [];\n }\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// create fk\",\n ...up,\n \"});\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// drop fk\",\n ...down,\n \"});\",\n \"}\",\n ];\n\n const foreignKeysString = foreigns\n .map((foreign) => foreign.columns.join(\"_\"))\n .join(\"_\");\n return [\n {\n table,\n type: \"foreign\",\n title: `foreign__${table}__${foreignKeysString}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n },\n ];\n }\n\n /*\n 마이그레이션 컬럼 배열 비교용 코드\n */\n showMigrationSet(which: \"Entity\" | \"DB\", migrationSet: MigrationSet): void {\n const { columns, indexes, foreigns } = migrationSet;\n const styledChalk =\n which === \"Entity\" ? chalk.bgGreen.black : chalk.bgBlue.black;\n console.log(\n styledChalk(\n `${which} ${migrationSet.table} Columns\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n columns.map((column) => {\n return {\n ..._.pick(column, [\n \"name\",\n \"type\",\n \"nullable\",\n \"unsigned\",\n \"length\",\n \"defaultTo\",\n \"precision\",\n \"scale\",\n ]),\n };\n }),\n [\n \"name\",\n \"type\",\n \"nullable\",\n \"unsigned\",\n \"length\",\n \"defaultTo\",\n \"precision\",\n \"scale\",\n ]\n );\n\n if (indexes.length > 0) {\n console.log(\n styledChalk(\n `${which} ${migrationSet.table} Indexes\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n indexes.map((index) => {\n return {\n ..._.pick(index, [\"type\", \"columns\", \"name\"]),\n };\n })\n );\n }\n\n if (foreigns.length > 0) {\n console.log(\n chalk.bgMagenta.black(\n `${which} ${migrationSet.table} Foreigns\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t\\t`\n )\n );\n console.table(\n foreigns.map((foreign) => {\n return {\n ..._.pick(foreign, [\"columns\", \"to\", \"onUpdate\", \"onDelete\"]),\n };\n })\n );\n }\n }\n\n async generateAlterCode_ColumnAndIndexes(\n table: string,\n entityColumns: MigrationColumn[],\n entityIndexes: MigrationIndex[],\n dbColumns: MigrationColumn[],\n dbIndexes: MigrationIndex[],\n dbForeigns: MigrationForeign[]\n ): Promise<GenMigrationCode[]> {\n /*\n 세부 비교 후 다른점 찾아서 코드 생성\n\n 1. 컬럼갯수 다름: MD에 있으나, DB에 없다면 추가\n 2. 컬럼갯수 다름: MD에 없으나, DB에 있다면 삭제\n 3. 그외 컬럼(컬럼 갯수가 동일하거나, 다른 경우 동일한 컬럼끼리) => alter\n 4. 다른거 다 동일하고 index만 변경되는 경우\n\n ** 컬럼명을 변경하는 경우는 따로 핸들링하지 않음\n => drop/add 형태의 마이그레이션 코드가 생성되는데, 수동으로 rename 코드로 수정하여 처리\n */\n\n // 각 컬럼 이름 기준으로 add, drop, alter 여부 확인\n const alterColumnsTo = this.getAlterColumnsTo(entityColumns, dbColumns);\n\n // 추출된 컬럼들을 기준으로 각각 라인 생성\n const alterColumnLinesTo = this.getAlterColumnLinesTo(\n alterColumnsTo,\n entityColumns,\n table,\n dbForeigns\n );\n\n // 인덱스의 add, drop 여부 확인\n const alterIndexesTo = this.getAlterIndexesTo(entityIndexes, dbIndexes);\n\n // fulltext index 분리\n const [ngramIndexes, standardIndexes] = _.partition(\n alterIndexesTo.add,\n (i) => i.type === \"fulltext\" && i.parser === \"ngram\"\n );\n\n // 인덱스가 삭제되는 경우, 컬럼과 같이 삭제된 케이스에는 drop에서 제외해야함!\n const indexNeedsToDrop = alterIndexesTo.drop.filter(\n (index) =>\n index.columns.every((colName) =>\n alterColumnsTo.drop.map((col) => col.name).includes(colName)\n ) === false\n );\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `await knex.schema.alterTable(\"${table}\", (table) => {`,\n // 1. add column\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.up : []),\n // 2. drop column\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.up : []),\n // 3. alter column\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.up : []),\n // 4. add index\n ...standardIndexes.map((index) => this.genIndexDefinition(index, table)),\n // 5. drop index\n ...indexNeedsToDrop.map(this.genIndexDropDefinition),\n \"});\",\n // ngram은 knex.raw로 처리하므로 alterTable 밖에서 실행\n ...ngramIndexes.map((index) => this.genIndexDefinition(index, table)),\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.down : []),\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.down : []),\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.down : []),\n ...alterIndexesTo.add\n .filter(\n (index) =>\n index.columns.every((colName) =>\n alterColumnsTo.add.map((col) => col.name).includes(colName)\n ) === false\n )\n .map(this.genIndexDropDefinition),\n ...indexNeedsToDrop.map((index) => this.genIndexDefinition(index, table)),\n \"});\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n ...([\"add\", \"drop\", \"alter\"] as const)\n .map((action) => {\n const len = alterColumnsTo[action].length;\n if (len > 0) {\n return action + len;\n }\n return null;\n })\n .filter((part) => part !== null),\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n }\n\n getAlterColumnsTo(\n entityColumns: MigrationColumn[],\n dbColumns: MigrationColumn[]\n ) {\n const columnsTo = {\n add: [] as MigrationColumn[],\n drop: [] as MigrationColumn[],\n alter: [] as MigrationColumn[],\n };\n\n // 컬럼명 기준 비교\n const extraColumns = {\n db: _.differenceBy(dbColumns, entityColumns, (col) => col.name),\n entity: _.differenceBy(entityColumns, dbColumns, (col) => col.name),\n };\n if (extraColumns.entity.length > 0) {\n columnsTo.add = columnsTo.add.concat(extraColumns.entity);\n }\n if (extraColumns.db.length > 0) {\n columnsTo.drop = columnsTo.drop.concat(extraColumns.db);\n }\n\n // 동일 컬럼명의 세부 필드 비교\n const sameDbColumns = _.intersectionBy(\n dbColumns,\n entityColumns,\n (col) => col.name\n );\n const sameMdColumns = _.intersectionBy(\n entityColumns,\n dbColumns,\n (col) => col.name\n );\n columnsTo.alter = _.differenceWith(sameDbColumns, sameMdColumns, (a, b) =>\n equal(a, b)\n );\n\n return columnsTo;\n }\n\n getAlterColumnLinesTo(\n columnsTo: ReturnType<Migrator[\"getAlterColumnsTo\"]>,\n entityColumns: MigrationColumn[],\n table: string,\n dbForeigns: MigrationForeign[]\n ) {\n let linesTo = {\n add: {\n up: [] as string[],\n down: [] as string[],\n },\n drop: {\n up: [] as string[],\n down: [] as string[],\n },\n alter: {\n up: [] as string[],\n down: [] as string[],\n },\n };\n\n linesTo.add = {\n up: [\"// add\", ...this.genColumnDefinitions(columnsTo.add)],\n down: [\n \"// rollback - add\",\n `table.dropColumns(${columnsTo.add\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n };\n\n // drop할 컬럼에 걸린 FK 찾기\n const dropColumnNames = columnsTo.drop.map((col) => col.name);\n const fkToDropBeforeColumn = dbForeigns.filter((fk) =>\n fk.columns.some((col) => dropColumnNames.includes(col))\n );\n\n const dropFkLines = fkToDropBeforeColumn.map((fk) => {\n const columnsStringQuote = fk.columns.map((col) => `'${col}'`).join(\",\");\n return `table.dropForeign([${columnsStringQuote}])`;\n });\n\n const restoreFkLines = this.genForeignDefinitions(\n table,\n fkToDropBeforeColumn\n ).up;\n\n linesTo.drop = {\n up: [\n ...(dropFkLines.length > 0\n ? [\"// drop foreign keys on columns to be dropped\", ...dropFkLines]\n : []),\n \"// drop columns\",\n `table.dropColumns(${columnsTo.drop\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n down: [\n \"// rollback - drop columns\",\n ...this.genColumnDefinitions(columnsTo.drop),\n ...(restoreFkLines.length > 0\n ? [\"// restore foreign keys\", ...restoreFkLines]\n : []),\n ],\n };\n linesTo.alter = columnsTo.alter.reduce(\n (r, dbColumn) => {\n const entityColumn = entityColumns.find(\n (col) => col.name == dbColumn.name\n );\n if (entityColumn === undefined) {\n return r;\n }\n\n // 컬럼 변경사항\n const columnDiffUp = _.difference(\n this.genColumnDefinitions([entityColumn]),\n this.genColumnDefinitions([dbColumn])\n );\n const columnDiffDown = _.difference(\n this.genColumnDefinitions([dbColumn]),\n this.genColumnDefinitions([entityColumn])\n );\n if (columnDiffUp.length > 0) {\n r.up = [\n ...r.up,\n \"// alter column\",\n ...columnDiffUp.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n r.down = [\n ...r.down,\n \"// rollback - alter column\",\n ...columnDiffDown.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n }\n\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n\n return linesTo;\n }\n\n getAlterIndexesTo(\n entityIndexes: MigrationIndex[],\n dbIndexes: MigrationIndex[]\n ) {\n // 인덱스 비교\n let indexesTo = {\n add: [] as MigrationIndex[],\n drop: [] as MigrationIndex[],\n };\n const extraIndexes = {\n db: _.differenceBy(dbIndexes, entityIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n entity: _.differenceBy(entityIndexes, dbIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n };\n if (extraIndexes.entity.length > 0) {\n indexesTo.add = indexesTo.add.concat(extraIndexes.entity);\n }\n if (extraIndexes.db.length > 0) {\n indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);\n }\n\n return indexesTo;\n }\n\n genIndexDefinition(index: MigrationIndex, table: string) {\n const methodMap = {\n index: \"index\",\n fulltext: \"index\",\n unique: \"unique\",\n };\n\n if (index.type === \"fulltext\" && index.parser === \"ngram\") {\n const indexName = `${table}_${index.columns.join(\"_\")}_index`;\n return `await knex.raw(\\`ALTER TABLE ${table} ADD FULLTEXT INDEX ${indexName} (${index.columns.join(\n \", \"\n )}) WITH PARSER ngram\\`);`;\n }\n\n return `table.${methodMap[index.type]}([${index.columns\n .map((col) => `'${col}'`)\n .join(\",\")}]${\n index.type === \"fulltext\" ? \", undefined, 'FULLTEXT'\" : \"\"\n })`;\n }\n\n genIndexDropDefinition(index: MigrationIndex) {\n const methodMap = {\n index: \"Index\",\n fulltext: \"Index\",\n unique: \"Unique\",\n };\n\n return `table.drop${methodMap[index.type]}([${index.columns\n .map((columnName) => `'${columnName}'`)\n .join(\",\")}])`;\n }\n\n async generateAlterCode_Foreigns(\n table: string,\n entityForeigns: MigrationForeign[],\n dbForeigns: MigrationForeign[],\n droppingColumns: MigrationColumn[] = []\n ): Promise<GenMigrationCode[]> {\n // console.log({ entityForeigns, dbForeigns });\n\n const getKey = (mf: MigrationForeign): string => {\n return [mf.columns.join(\"-\"), mf.to].join(\"///\");\n };\n\n // 삭제될 컬럼명 목록\n const droppingColumnNames = droppingColumns.map((col) => col.name);\n\n const fkTo = entityForeigns.reduce(\n (result, entityF) => {\n const matchingDbF = dbForeigns.find(\n (dbF) => getKey(entityF) === getKey(dbF)\n );\n if (!matchingDbF) {\n result.add.push(entityF);\n return result;\n }\n\n if (equal(entityF, matchingDbF) === false) {\n result.alterSrc.push(matchingDbF);\n result.alterDst.push(entityF);\n return result;\n }\n return result;\n },\n {\n add: [] as MigrationForeign[],\n drop: [] as MigrationForeign[],\n alterSrc: [] as MigrationForeign[],\n alterDst: [] as MigrationForeign[],\n }\n );\n\n // dbForeigns에는 있지만 entityForeigns에는 없는 경우 (삭제된 FK)\n // 단, 삭제될 컬럼의 FK는 제외 (generateAlterCode_ColumnAndIndexes에서 처리)\n dbForeigns.forEach((dbF) => {\n const matchingEntityF = entityForeigns.find(\n (entityF) => getKey(entityF) === getKey(dbF)\n );\n if (!matchingEntityF) {\n // 이 FK의 컬럼이 삭제될 컬럼 목록에 있는지 확인\n const isColumnDropping = dbF.columns.some((col) =>\n droppingColumnNames.includes(col)\n );\n // 컬럼이 삭제되지 않는 경우에만 FK drop 목록에 추가\n if (!isColumnDropping) {\n fkTo.drop.push(dbF);\n }\n }\n });\n\n const linesTo = {\n add: this.genForeignDefinitions(table, fkTo.add),\n drop: this.genForeignDefinitions(table, fkTo.drop),\n alterSrc: this.genForeignDefinitions(table, fkTo.alterSrc),\n alterDst: this.genForeignDefinitions(table, fkTo.alterDst),\n };\n\n // drop fk columns인 경우(생성될 코드 없는 경우) 패스\n const hasLines = Object.values(linesTo).some(\n (l) => l.up.length > 0 || l.down.length > 0\n );\n if (!hasLines) {\n return [];\n }\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.drop.down,\n ...linesTo.add.up,\n ...linesTo.alterSrc.down,\n ...linesTo.alterDst.up,\n \"})\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.add.down,\n ...linesTo.alterDst.down,\n ...linesTo.alterSrc.up,\n ...linesTo.drop.up,\n \"})\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n \"foreigns\",\n // TODO 바뀌는 부분\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n }\n\n async destroy(): Promise<void> {\n await Promise.all(\n this.targets.apply.map((db) => {\n return db.destroy();\n })\n );\n }\n}\n\ntype DBColumn = {\n Field: string;\n Type: string;\n Null: string;\n Key: string;\n Default: string | null;\n Extra: string;\n};\ntype DBIndex = {\n Table: string;\n Non_unique: number;\n Key_name: string;\n Seq_in_index: number;\n Column_name: string;\n Collation: string | null;\n Cardinality: number | null;\n Sub_part: number | null;\n Packed: string | null;\n Null: string;\n Index_type: string;\n Comment: string;\n Index_comment: string;\n Visible: string;\n Expression: string | null;\n};\ntype DBForeign = {\n keyName: string;\n from: string;\n referencesTable: string;\n referencesField: string;\n onDelete: string;\n onUpdate: string;\n};\n"],"names":["Migrator","options","mode","targets","dbConfig","Sonamu","devDB","knex","development_master","testDB","test","fixtureLocalDB","fixture_local","applyDBs","connection","host","fixture_remote","database","fixtureRemoteDB","push","compare","pending","shadow","apply","productionDB","production_master","Error","getMigrationCodes","srcMigrationsDir","distMigrationsDir","srcMigrations","distMigrations","normal","onlyTs","onlyJs","apiRootPath","exists","mkdir","recursive","readdir","filter","f","endsWith","map","split","_","intersection","filename","name","path","join","sort","a","b","difference","getStatus","connKeys","statuses","preparedCodes","length","console","debug","ServiceUnavailableException","Promise","all","execSync","replace","Object","keys","key","connKey","knexOptions","tConn","status","currentVersion","err","migrate","warn","chalk","yellow","JSON","stringify","fdList","list","fd","file","destroy","connString","user","port","status0conn","compareDBconn","genCodes","find","undefined","compareMigrations","conns","codes","runAction","action","configs","result","uniqBy","target","c","config","batchNo","applied","latest","rollback","delCodes","codeNames","delFiles","res","some","conn","codeName","includes","flat","delFile","log","red","unlink","sum","generatePreparedCodes","migrationsDir","index","pcode","dateTag","filePath","green","entries","formatted","DateTime","local","plus","seconds","toFormat","title","writeFile","clearPendingList","pendingList","delList","p","df","cleanUpDist","check","table","run","answer","code","prompts","type","message","initial","value","time","blue","runShadowTest","timeEnd","applyDb","label","client","connectionSettings","rollbackAllResult","db","forceFreeMigrationsLock","dir","depth","force","files","diffOnSrc","diffOnDist","filesToRm","getFilesUnder","migrationPath","startsWith","src","dist","differenceBy","tdb","tdbConn","shadowDatabase","tmpSqlPath","sdb","e","magenta","password","raw","error","resetAll","compareDB","entityIds","entitySetsWithJoinTable","joinTablesWithDup","joinTables","entitySets","EntityManager","getAllIds","entityId","entity","get","props","getMigrationSetFromEntity","entitySet","values","groupBy","jt","tables","indexes","flatMap","t","columns","dbSet","replaceColumnDefaultTo","entityColumns","dbColumns","entityIndexes","dbIndexes","replaceNoActionOnMySQL","entityForeigns","dbForeigns","droppingColumns","alterCodes","isEqualColumns","isEqualIndexes","getMigrationSetFromDB","generateCreateCode_ColumnAndIndexes","generateCreateCode_Foreign","foreigns","col","defaultTo","String","Number","toFixed","scale","sortBy","c1","c2","onDelete","onUpdate","to","equal","omit","generateAlterCode_ColumnAndIndexes","generateAlterCode_Foreigns","every","alterCode","codeA","codeB","dbIndexesGroup","parseIndexType","readTable","isKnexError","dbColumn","dbColType","resolveDBColType","Type","Field","nullable","Null","Default","dbIndex","Key_name","dbForeign","keyName","Index_type","Non_unique","currentIndexes","currentIndex","Column_name","from","referencesTable","referencesField","colType","colField","rawType","unsigned","matched","match","parseInt","precision","tableName","_cols","cols","row","ddl","foreignKeys","Extra","line","onClause","onUpdateFull","_onUpdate","trim","migrationSet","reduce","r","prop","isVirtualProp","isHasManyRelationProp","isRelationProp","isTextProp","textType","isEnumProp","column","isIntegerProp","isStringProp","dbDefault","isDecimalProp","isFloatProp","isManyToManyRelationProp","relMd","with","table1","table2","through","inflection","joinTable","singularize","fields","field","isBelongsToOneRelationProp","isOneToOneRelationProp","hasJoinColumn","idColumnName","useConstraint","underscore","pluralize","toLowerCase","concat","genColumnDefinitions","chains","columnType","extraType","genIndexDefinitions","methodMap","fulltext","unique","lines","uniq","genForeignDefinitions","foreign","columnsStringQuote","up","down","ngramIndexes","standardIndexes","partition","i","parser","genIndexDefinition","prettier","format","foreignKeysString","showMigrationSet","which","styledChalk","bgGreen","black","bgBlue","pick","bgMagenta","alterColumnsTo","alterColumnLinesTo","alterIndexesTo","indexNeedsToDrop","getAlterColumnsTo","getAlterColumnLinesTo","getAlterIndexesTo","add","drop","colName","alter","genIndexDropDefinition","len","part","columnsTo","extraColumns","sameDbColumns","intersectionBy","sameMdColumns","differenceWith","linesTo","dropColumnNames","fkToDropBeforeColumn","fk","dropFkLines","restoreFkLines","entityColumn","columnDiffUp","columnDiffDown","l","indexesTo","extraIndexes","indexName","columnName","getKey","droppingColumnNames","fkTo","hasLines","mf","entityF","matchingDbF","dbF","alterSrc","alterDst","forEach","matchingEntityF","isColumnDropping"],"mappings":"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"}