sonamu 0.5.5 → 0.5.7

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.
Files changed (52) hide show
  1. package/dist/api/decorators.d.ts +1 -0
  2. package/dist/api/decorators.d.ts.map +1 -1
  3. package/dist/api/decorators.js +1 -1
  4. package/dist/api/decorators.js.map +1 -1
  5. package/dist/api/sonamu.d.ts.map +1 -1
  6. package/dist/api/sonamu.js +1 -1
  7. package/dist/api/sonamu.js.map +1 -1
  8. package/dist/bin/build-config.d.ts +4 -0
  9. package/dist/bin/build-config.d.ts.map +1 -1
  10. package/dist/bin/build-config.js +1 -1
  11. package/dist/bin/build-config.js.map +1 -1
  12. package/dist/bin/cli-wrapper.js +1 -1
  13. package/dist/bin/cli-wrapper.js.map +1 -1
  14. package/dist/database/db.d.ts +3 -0
  15. package/dist/database/db.d.ts.map +1 -1
  16. package/dist/database/db.js +1 -1
  17. package/dist/database/db.js.map +1 -1
  18. package/dist/database/puri-wrapper.d.ts +22 -10
  19. package/dist/database/puri-wrapper.d.ts.map +1 -1
  20. package/dist/database/puri-wrapper.js +1 -1
  21. package/dist/database/puri-wrapper.js.map +1 -1
  22. package/dist/database/puri.d.ts +91 -65
  23. package/dist/database/puri.d.ts.map +1 -1
  24. package/dist/database/puri.js +1 -1
  25. package/dist/database/puri.js.map +1 -1
  26. package/dist/database/puri.types.d.ts +28 -42
  27. package/dist/database/puri.types.d.ts.map +1 -1
  28. package/dist/database/transaction-context.d.ts +3 -3
  29. package/dist/database/transaction-context.d.ts.map +1 -1
  30. package/dist/database/transaction-context.js.map +1 -1
  31. package/dist/templates/service.template.d.ts.map +1 -1
  32. package/dist/templates/service.template.js +1 -1
  33. package/dist/templates/service.template.js.map +1 -1
  34. package/dist/types/types.d.ts +1 -1
  35. package/dist/types/types.d.ts.map +1 -1
  36. package/dist/types/types.js.map +1 -1
  37. package/package.json +1 -2
  38. package/src/api/decorators.ts +14 -5
  39. package/src/api/sonamu.ts +21 -20
  40. package/src/bin/build-config.ts +7 -3
  41. package/src/bin/cli-wrapper.ts +31 -12
  42. package/src/database/db.ts +44 -9
  43. package/src/database/puri-wrapper.ts +104 -26
  44. package/src/database/puri.ts +434 -543
  45. package/src/database/puri.types.ts +99 -200
  46. package/src/database/transaction-context.ts +4 -4
  47. package/src/templates/service.template.ts +10 -1
  48. package/src/types/types.ts +1 -1
  49. package/dist/entity/migrator.d.ts +0 -135
  50. package/dist/entity/migrator.d.ts.map +0 -1
  51. package/dist/entity/migrator.js +0 -2
  52. package/dist/entity/migrator.js.map +0 -1
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"Migrator",{enumerable:true,get:function(){return Migrator}});var _lodash=/*#__PURE__*/_interop_require_default(require("lodash"));var _knex=/*#__PURE__*/_interop_require_default(require("knex"));var _prettier=/*#__PURE__*/_interop_require_default(require("prettier"));var _chalk=/*#__PURE__*/_interop_require_default(require("chalk"));var _luxon=require("luxon");var _promises=require("fs/promises");var _fsutils=require("../utils/fs-utils");var _fastdeepequal=/*#__PURE__*/_interop_require_default(require("fast-deep-equal"));var _inflection=/*#__PURE__*/_interop_require_default(require("inflection"));var _prompts=/*#__PURE__*/_interop_require_default(require("prompts"));var _child_process=require("child_process");var _path=/*#__PURE__*/_interop_require_default(require("path"));var _types=require("../types/types");var _entitymanager=require("./entity-manager");var _api=require("../api");var _soexceptions=require("../exceptions/so-exceptions");function _array_like_to_array(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _array_with_holes(arr){if(Array.isArray(arr))return arr}function _array_without_holes(arr){if(Array.isArray(arr))return _array_like_to_array(arr)}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value}catch(error){reject(error);return}if(info.done){resolve(value)}else{Promise.resolve(value).then(_next,_throw)}}function _async_to_generator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value)}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err)}_next(undefined)})}}function _class_call_check(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function")}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor)}}function _create_class(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor}function _define_property(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true})}else{obj[key]=value}return obj}function _interop_require_default(obj){return obj&&obj.__esModule?obj:{default:obj}}function _iterable_to_array(iter){if(typeof Symbol!=="undefined"&&iter[Symbol.iterator]!=null||iter["@@iterator"]!=null)return Array.from(iter)}function _iterable_to_array_limit(arr,i){var _i=arr==null?null:typeof Symbol!=="undefined"&&arr[Symbol.iterator]||arr["@@iterator"];if(_i==null)return;var _arr=[];var _n=true;var _d=false;var _s,_e;try{for(_i=_i.call(arr);!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break}}catch(err){_d=true;_e=err}finally{try{if(!_n&&_i["return"]!=null)_i["return"]()}finally{if(_d)throw _e}}return _arr}function _non_iterable_rest(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _non_iterable_spread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _object_spread(target){for(var i=1;i<arguments.length;i++){var source=arguments[i]!=null?arguments[i]:{};var ownKeys=Object.keys(source);if(typeof Object.getOwnPropertySymbols==="function"){ownKeys=ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym){return Object.getOwnPropertyDescriptor(source,sym).enumerable}))}ownKeys.forEach(function(key){_define_property(target,key,source[key])})}return target}function ownKeys(object,enumerableOnly){var keys=Object.keys(object);if(Object.getOwnPropertySymbols){var symbols=Object.getOwnPropertySymbols(object);if(enumerableOnly){symbols=symbols.filter(function(sym){return Object.getOwnPropertyDescriptor(object,sym).enumerable})}keys.push.apply(keys,symbols)}return keys}function _object_spread_props(target,source){source=source!=null?source:{};if(Object.getOwnPropertyDescriptors){Object.defineProperties(target,Object.getOwnPropertyDescriptors(source))}else{ownKeys(Object(source)).forEach(function(key){Object.defineProperty(target,key,Object.getOwnPropertyDescriptor(source,key))})}return target}function _sliced_to_array(arr,i){return _array_with_holes(arr)||_iterable_to_array_limit(arr,i)||_unsupported_iterable_to_array(arr,i)||_non_iterable_rest()}function _to_consumable_array(arr){return _array_without_holes(arr)||_iterable_to_array(arr)||_unsupported_iterable_to_array(arr)||_non_iterable_spread()}function _unsupported_iterable_to_array(o,minLen){if(!o)return;if(typeof o==="string")return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(n);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}function _ts_generator(thisArg,body){var f,y,t,_={label:0,sent:function(){if(t[0]&1)throw t[1];return t[1]},trys:[],ops:[]},g=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return g.next=verb(0),g["throw"]=verb(1),g["return"]=verb(2),typeof Symbol==="function"&&(g[Symbol.iterator]=function(){return this}),g;function verb(n){return function(v){return step([n,v])}}function step(op){if(f)throw new TypeError("Generator is already executing.");while(g&&(g=0,op[0]&&(_=0)),_)try{if(f=1,y&&(t=op[0]&2?y["return"]:op[0]?y["throw"]||((t=y["return"])&&t.call(y),0):y.next)&&!(t=t.call(y,op[1])).done)return t;if(y=0,t)op=[op[0]&2,t.value];switch(op[0]){case 0:case 1:t=op;break;case 4:_.label++;return{value:op[1],done:false};case 5:_.label++;y=op[1];op=[0];continue;case 7:op=_.ops.pop();_.trys.pop();continue;default:if(!(t=_.trys,t=t.length>0&&t[t.length-1])&&(op[0]===6||op[0]===2)){_=0;continue}if(op[0]===3&&(!t||op[1]>t[0]&&op[1]<t[3])){_.label=op[1];break}if(op[0]===6&&_.label<t[1]){_.label=t[1];t=op;break}if(t&&_.label<t[2]){_.label=t[2];_.ops.push(op);break}if(t[2])_.ops.pop();_.trys.pop();continue}op=body.call(thisArg,_)}catch(e){op=[6,e];y=0}finally{f=t=0}if(op[0]&5)throw op[1];return{value:op[0]?op[1]:void 0,done:true}}}var Migrator=/*#__PURE__*/function(){"use strict";function Migrator(options){_class_call_check(this,Migrator);_define_property(this,"mode",void 0);_define_property(this,"targets",void 0);this.mode=options.mode;var dbConfig=_api.Sonamu.dbConfig;if(this.mode==="dev"){var devDB=(0,_knex.default)(dbConfig.development_master);var testDB=(0,_knex.default)(dbConfig.test);var fixtureLocalDB=(0,_knex.default)(dbConfig.fixture_local);var applyDBs=[devDB,testDB,fixtureLocalDB];if(dbConfig.fixture_local.connection.host!==dbConfig.fixture_remote.connection.host||dbConfig.fixture_local.connection.database!==dbConfig.fixture_remote.connection.database){var fixtureRemoteDB=(0,_knex.default)(dbConfig.fixture_remote);applyDBs.push(fixtureRemoteDB)}this.targets={compare:devDB,pending:devDB,shadow:testDB,apply:applyDBs}}else if(this.mode==="deploy"){var productionDB=(0,_knex.default)(dbConfig.production_master);var testDB1=(0,_knex.default)(dbConfig.test);this.targets={pending:productionDB,shadow:testDB1,apply:[productionDB]}}else{throw new Error("잘못된 모드 ".concat(this.mode," 입력"))}}_create_class(Migrator,[{key:"getMigrationCodes",value:function getMigrationCodes(){return _async_to_generator(function(){var srcMigrationsDir,distMigrationsDir,srcMigrations,distMigrations,normal,onlyTs,onlyJs;return _ts_generator(this,function(_state){switch(_state.label){case 0:srcMigrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");distMigrationsDir="".concat(_api.Sonamu.apiRootPath,"/dist/migrations");return[4,(0,_fsutils.exists)(srcMigrationsDir)];case 1:if(!!_state.sent())return[3,3];return[4,(0,_promises.mkdir)(srcMigrationsDir,{recursive:true})];case 2:_state.sent();_state.label=3;case 3:return[4,(0,_fsutils.exists)(distMigrationsDir)];case 4:if(!!_state.sent())return[3,6];return[4,(0,_promises.mkdir)(distMigrationsDir,{recursive:true})];case 5:_state.sent();_state.label=6;case 6:return[4,(0,_promises.readdir)(srcMigrationsDir)];case 7:srcMigrations=_state.sent().filter(function(f){return f.endsWith(".ts")}).map(function(f){return f.split(".")[0]});return[4,(0,_promises.readdir)(distMigrationsDir)];case 8:distMigrations=_state.sent().filter(function(f){return f.endsWith(".js")}).map(function(f){return f.split(".")[0]});normal=_lodash.default.intersection(srcMigrations,distMigrations).map(function(filename){return{name:filename,path:_path.default.join(srcMigrationsDir,filename)+".ts"}}).sort(function(a,b){return a>b?1:-1});onlyTs=_lodash.default.difference(srcMigrations,distMigrations).map(function(filename){return{name:filename,path:_path.default.join(srcMigrationsDir,filename)+".ts"}});onlyJs=_lodash.default.difference(distMigrations,srcMigrations).map(function(filename){return{name:filename,path:_path.default.join(distMigrationsDir,filename)+".js"}});return[2,{normal:normal,onlyTs:onlyTs,onlyJs:onlyJs}]}})})()}},{key:"getStatus",value:function getStatus(){return _async_to_generator(function(){var _this,_ref,normal,onlyTs,onlyJs,connKeys,statuses,preparedCodes;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;return[4,this.getMigrationCodes()];case 1:_ref=_state.sent(),normal=_ref.normal,onlyTs=_ref.onlyTs,onlyJs=_ref.onlyJs;if(onlyTs.length>0){console.debug({onlyTs:onlyTs});throw new _soexceptions.ServiceUnavailableException("There are un-compiled TS migration files.\nPlease compile them first.\n\n".concat(onlyTs.map(function(f){return f.name}).join("\n")))}if(!(onlyJs.length>0))return[3,3];console.debug({onlyJs:onlyJs});return[4,Promise.all(onlyJs.map(function(f){return _async_to_generator(function(){return _ts_generator(this,function(_state){(0,_child_process.execSync)("rm -f ".concat(f.path.replace("/src/","/dist/").replace(".ts",".js")));return[2]})})()}))];case 2:_state.sent();_state.label=3;case 3:connKeys=Object.keys(_api.Sonamu.dbConfig).filter(function(key){return key.endsWith("_slave")===false});return[4,Promise.all(connKeys.map(function(connKey){return _async_to_generator(function(){var knexOptions,tConn,status,pending,currentVersion,connection,_connection_user;return _ts_generator(this,function(_state){switch(_state.label){case 0:knexOptions=_api.Sonamu.dbConfig[connKey];tConn=(0,_knex.default)(knexOptions);return[4,function(){return _async_to_generator(function(){var err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.status()];case 1:return[2,_state.sent()];case 2:err=_state.sent();console.warn(_chalk.default.yellow("".concat(connKey,"의 마이그레이션 상태를 가져오는 데에 실패하였습니다. 데이터베이스가 올바르게 구성되지 않은 것 같습니다. 확인하시고 다시 시도해주세요.\n시도한 연결 설정:\n").concat(JSON.stringify(knexOptions.connection,null,2),"\n발생한 에러:\n").concat(err,"\n")));return[2,"error"];case 3:return[2]}})})()}()];case 1:status=_state.sent();return[4,function(){return _async_to_generator(function(){var _ref,fdList,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),fdList=_ref[1];return[2,fdList.map(function(fd){return fd.file.replace(".js","")})];case 2:err=_state.sent();return[2,[]];case 3:return[2]}})})()}()];case 2:pending=_state.sent();return[4,function(){return _async_to_generator(function(){var err;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,2,,3]);return[4,tConn.migrate.currentVersion()];case 1:return[2,_state.sent()];case 2:err=_state.sent();return[2,"error"];case 3:return[2]}})})()}()];case 3:currentVersion=_state.sent();connection=knexOptions.connection;return[4,tConn.destroy()];case 4:_state.sent();return[2,{name:connKey.replace("_master",""),connKey:connKey,connString:"mysql2://".concat((_connection_user=connection.user)!==null&&_connection_user!==void 0?_connection_user:"","@").concat(connection.host,":").concat(connection.port,"/").concat(connection.database),currentVersion:currentVersion,status:status,pending:pending}]}})})()}))];case 4:statuses=_state.sent();return[4,function(){return _async_to_generator(function(){var status0conn,compareDBconn,genCodes;return _ts_generator(this,function(_state){switch(_state.label){case 0:status0conn=statuses.find(function(status){return status.status===0});if(status0conn===undefined){return[2,[]]}compareDBconn=(0,_knex.default)(_api.Sonamu.dbConfig[status0conn.connKey]);return[4,this.compareMigrations(compareDBconn)];case 1:genCodes=_state.sent();return[4,compareDBconn.destroy()];case 2:_state.sent();return[2,genCodes]}})}).call(_this)}()];case 5:preparedCodes=_state.sent();return[2,{conns:statuses,codes:normal,preparedCodes:preparedCodes}]}})}).call(this)}},{key:"runAction",value:function runAction(action,targets){return _async_to_generator(function(){var configs,conns,result;return _ts_generator(this,function(_state){switch(_state.label){case 0:configs=_lodash.default.uniqBy(targets.map(function(target){return{connKey:target,options:_api.Sonamu.dbConfig[target]}}).filter(function(c){return c.options!==undefined}),function(param){var options=param.options;var _options_connection_port;return"".concat(options.connection.host,":").concat((_options_connection_port=options.connection.port)!==null&&_options_connection_port!==void 0?_options_connection_port:3306,"/").concat(options.connection.database)});return[4,Promise.all(configs.map(function(config){return _async_to_generator(function(){return _ts_generator(this,function(_state){return[2,{connKey:config.connKey,knex:(0,_knex.default)(config.options)}]})})()}))];case 1:conns=_state.sent();return[4,function(){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(action){case"latest":return[2,Promise.all(conns.map(function(param){var connKey=param.connKey,knex=param.knex;return _async_to_generator(function(){var _ref,batchNo,applied;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,knex.migrate.latest()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];return[2,{connKey:connKey,batchNo:batchNo,applied:applied}]}})})()}))];case"rollback":return[2,Promise.all(conns.map(function(param){var connKey=param.connKey,knex=param.knex;return _async_to_generator(function(){var _ref,batchNo,applied;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,knex.migrate.rollback()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];return[2,{connKey:connKey,batchNo:batchNo,applied:applied}]}})})()}))]}return[2]})})()}()];case 2:result=_state.sent();return[4,Promise.all(conns.map(function(param){var knex=param.knex;return knex.destroy()}))];case 3:_state.sent();return[2,result]}})})()}},{key:"delCodes",value:function delCodes(codeNames){return _async_to_generator(function(){var conns,delFiles,res;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.getStatus()];case 1:conns=_state.sent().conns;if(conns.some(function(conn){return codeNames.some(function(codeName){return conn.pending.includes(codeName)===false})})){throw new Error("You cannot delete a migration file if there is already applied.")}delFiles=codeNames.map(function(codeName){return["".concat(_api.Sonamu.apiRootPath,"/src/migrations/").concat(codeName,".ts"),"".concat(_api.Sonamu.apiRootPath,"/dist/migrations/").concat(codeName,".js")]}).flat();return[4,Promise.all(delFiles.map(function(delFile){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(0,_fsutils.exists)(delFile)];case 1:if(!_state.sent())return[3,3];console.log(_chalk.default.red("DELETE: ".concat(delFile)));return[4,(0,_promises.unlink)(delFile)];case 2:_state.sent();return[2,delFiles.includes(".ts")?1:0];case 3:return[2,0]}})})()}))];case 2:res=_state.sent();return[2,_lodash.default.sum(res)]}})}).call(this)}},{key:"generatePreparedCodes",value:function generatePreparedCodes(){return _async_to_generator(function(){var preparedCodes,migrationsDir,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,_step_value,index,pcode,dateTag,filePath,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.getStatus()];case 1:preparedCodes=_state.sent().preparedCodes;if(preparedCodes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2,0]}migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=2;case 2:_state.trys.push([2,7,8,9]);_iterator=preparedCodes.entries()[Symbol.iterator]();_state.label=3;case 3:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,6];_step_value=_sliced_to_array(_step.value,2),index=_step_value[0],pcode=_step_value[1];if(!pcode.formatted)return[3,5];dateTag=_luxon.DateTime.local().plus({seconds:index}).toFormat("yyyyMMddHHmmss");filePath="".concat(migrationsDir,"/").concat(dateTag,"_").concat(pcode.title,".ts");return[4,(0,_promises.writeFile)(filePath,pcode.formatted)];case 4:_state.sent();console.log(_chalk.default.green("MIGRTAION CREATED ".concat(filePath)));_state.label=5;case 5:_iteratorNormalCompletion=true;return[3,3];case 6:return[3,9];case 7:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,9];case 8:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 9:return[2,preparedCodes.length]}})}).call(this)}},{key:"clearPendingList",value:function clearPendingList(){return _async_to_generator(function(){var _ref,pendingList,migrationsDir,delList,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,p,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.targets.pending.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),pendingList=_ref[1];migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");delList=pendingList.map(function(df){return _path.default.join(migrationsDir,df.file).replace(".js",".ts")});_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=2;case 2:_state.trys.push([2,8,9,10]);_iterator=delList[Symbol.iterator]();_state.label=3;case 3:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,7];p=_step.value;return[4,(0,_fsutils.exists)(p)];case 4:if(!_state.sent())return[3,6];return[4,(0,_promises.unlink)(p)];case 5:_state.sent();_state.label=6;case 6:_iteratorNormalCompletion=true;return[3,3];case 7:return[3,10];case 8:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,10];case 9:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 10:return[4,this.cleanUpDist(true)];case 11:_state.sent();return[2]}})}).call(this)}},{key:"check",value:function check(){return _async_to_generator(function(){var codes;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.compareMigrations(this.targets.compare)];case 1:codes=_state.sent();if(codes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2]}console.table(codes,["type","title"]);console.log(codes[0]);return[2]}})}).call(this)}},{key:"run",value:function run(){return _async_to_generator(function(){var _ref,pendingList,answer,codes,answer1,migrationsDir,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,_step_value,index,code,dateTag,filePath,err;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.targets.pending.migrate.list()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),pendingList=_ref[1];if(!(pendingList.length>0))return[3,5];console.log(_chalk.default.red("pending 된 마이그레이션이 존재합니다."),pendingList.map(function(pending){return pending.file}));return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"Shadow DB 테스트를 진행하시겠습니까?",initial:true})];case 2:answer=_state.sent();if(answer.value===false){return[2]}console.time(_chalk.default.blue("Migrator - runShadowTest"));return[4,this.runShadowTest()];case 3:_state.sent();console.timeEnd(_chalk.default.blue("Migrator - runShadowTest"));return[4,Promise.all(this.targets.apply.map(function(applyDb){return _async_to_generator(function(){var label,_ref;return _ts_generator(this,function(_state){switch(_state.label){case 0:label=_chalk.default.green("APPLIED ".concat(applyDb.client.connectionSettings.host," ").concat(applyDb.client.database()));console.time(label);return[4,applyDb.migrate.latest()];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),1]);console.timeEnd(label);return[2]}})})()}))];case 4:_state.sent();_state.label=5;case 5:return[4,this.compareMigrations(this.targets.compare)];case 6:codes=_state.sent();if(codes.length===0){console.log(_chalk.default.green("\n현재 모두 싱크된 상태입니다."));return[2]}console.table(codes,["type","title"]);return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"마이그레이션 코드를 생성하시겠습니까?",initial:false})];case 7:answer1=_state.sent();if(answer1.value===false){return[2]}migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=8;case 8:_state.trys.push([8,13,14,15]);_iterator=codes.entries()[Symbol.iterator]();_state.label=9;case 9:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,12];_step_value=_sliced_to_array(_step.value,2),index=_step_value[0],code=_step_value[1];if(!code.formatted)return[3,11];dateTag=_luxon.DateTime.local().plus({seconds:index}).toFormat("yyyyMMddHHmmss");filePath="".concat(migrationsDir,"/").concat(dateTag,"_").concat(code.title,".ts");return[4,(0,_promises.writeFile)(filePath,code.formatted)];case 10:_state.sent();console.log(_chalk.default.green("MIGRTAION CREATED ".concat(filePath)));_state.label=11;case 11:_iteratorNormalCompletion=true;return[3,9];case 12:return[3,15];case 13:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,15];case 14:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 15:return[2]}})}).call(this)}},{key:"rollback",value:function rollback(){return _async_to_generator(function(){var rollbackAllResult;return _ts_generator(this,function(_state){switch(_state.label){case 0:console.time(_chalk.default.red("rollback:"));return[4,Promise.all(this.targets.apply.map(function(db){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,db.migrate.forceFreeMigrationsLock()];case 1:_state.sent();return[2,db.migrate.rollback(undefined,false)]}})})()}))];case 1:rollbackAllResult=_state.sent();console.dir({rollbackAllResult:rollbackAllResult},{depth:null});console.timeEnd(_chalk.default.red("rollback:"));return[2]}})}).call(this)}},{key:"cleanUpDist",value:function cleanUpDist(){var force=arguments.length>0&&arguments[0]!==void 0?arguments[0]:false;return _async_to_generator(function(){var files,_tmp,diffOnSrc,diffOnDist,answer,filesToRm,_iteratorNormalCompletion,_didIteratorError,_iteratorError,_iterator,_step,filePath,err;function getFilesUnder(dir){return _async_to_generator(function(){var migrationPath;return _ts_generator(this,function(_state){switch(_state.label){case 0:migrationPath=_path.default.join(_api.Sonamu.apiRootPath,dir,"migrations");return[4,(0,_fsutils.exists)(migrationPath)];case 1:if(!!_state.sent())return[3,3];return[4,(0,_promises.mkdir)(migrationPath,{recursive:true})];case 2:_state.sent();_state.label=3;case 3:return[4,(0,_promises.readdir)(migrationPath)];case 4:return[2,_state.sent().filter(function(filename){return filename.startsWith(".")===false})]}})})()}return _ts_generator(this,function(_state){switch(_state.label){case 0:_tmp={};return[4,getFilesUnder("src")];case 1:_tmp.src=_state.sent();return[4,getFilesUnder("dist")];case 2:files=(_tmp.dist=_state.sent(),_tmp);diffOnSrc=_lodash.default.differenceBy(files.src,files.dist,function(filename){return filename.split(".")[0]});if(diffOnSrc.length>0){throw new Error("컴파일 되지 않은 파일이 있습니다.\n"+diffOnSrc.join("\n"))}diffOnDist=_lodash.default.differenceBy(files.dist,files.src,function(filename){return filename.split(".")[0]});if(!(diffOnDist.length>0))return[3,13];console.log(_chalk.default.red("원본 ts파일을 찾을 수 없는 js파일이 있습니다."));console.log(diffOnDist);if(!!force)return[3,4];return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"삭제를 진행하시겠습니까?",initial:true})];case 3:answer=_state.sent();if(answer.value===false){return[2]}_state.label=4;case 4:filesToRm=diffOnDist.map(function(filename){return _path.default.join(_api.Sonamu.apiRootPath,"dist","migrations",filename)});_iteratorNormalCompletion=true,_didIteratorError=false,_iteratorError=undefined;_state.label=5;case 5:_state.trys.push([5,10,11,12]);_iterator=filesToRm[Symbol.iterator]();_state.label=6;case 6:if(!!(_iteratorNormalCompletion=(_step=_iterator.next()).done))return[3,9];filePath=_step.value;return[4,(0,_promises.unlink)(filePath)];case 7:_state.sent();_state.label=8;case 8:_iteratorNormalCompletion=true;return[3,6];case 9:return[3,12];case 10:err=_state.sent();_didIteratorError=true;_iteratorError=err;return[3,12];case 11:try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}return[7];case 12:console.log(_chalk.default.green("".concat(filesToRm.length,"건 삭제되었습니다!")));_state.label=13;case 13:return[2]}})})()}},{key:"runShadowTest",value:function runShadowTest(){return _async_to_generator(function(){var tdb,tdbConn,shadowDatabase,tmpSqlPath,_tdbConn_port,_tdbConn_port1,sdb,_ref,batchNo,applied,e;return _ts_generator(this,function(_state){switch(_state.label){case 0:tdb=(0,_knex.default)(_api.Sonamu.dbConfig.test);tdbConn=_api.Sonamu.dbConfig.test.connection;shadowDatabase=tdbConn.database+"__migration_shadow";tmpSqlPath="/tmp/".concat(shadowDatabase,".sql");console.log(_chalk.default.magenta("".concat(tdbConn.database,"의 데이터 ").concat(tmpSqlPath,"로 덤프")));(0,_child_process.execSync)("mysqldump -h".concat(tdbConn.host," -P").concat((_tdbConn_port=tdbConn.port)!==null&&_tdbConn_port!==void 0?_tdbConn_port:3306," -u").concat(tdbConn.user," -p'").concat(tdbConn.password,"' ").concat(tdbConn.database," --single-transaction --no-create-db --triggers > ").concat(tmpSqlPath,";"));(0,_child_process.execSync)("sed -i'' -e 's/`".concat(tdbConn.database,"`/`").concat(shadowDatabase,"`/g' ").concat(tmpSqlPath,";"));console.log(_chalk.default.magenta("".concat(shadowDatabase," 리셋")));return[4,tdb.raw("DROP DATABASE IF EXISTS `".concat(shadowDatabase,"`;"))];case 1:_state.sent();return[4,tdb.raw("CREATE DATABASE `".concat(shadowDatabase,"`;"))];case 2:_state.sent();console.log(_chalk.default.magenta("".concat(shadowDatabase," 데이터베이스 생성")));(0,_child_process.execSync)("mysql -h".concat(tdbConn.host," -P").concat((_tdbConn_port1=tdbConn.port)!==null&&_tdbConn_port1!==void 0?_tdbConn_port1:3306," -u").concat(tdbConn.user," -p'").concat(tdbConn.password,"' ").concat(shadowDatabase," < ").concat(tmpSqlPath,";"));sdb=(0,_knex.default)(_object_spread_props(_object_spread({},_api.Sonamu.dbConfig.test),{connection:_object_spread_props(_object_spread({},tdbConn),{database:shadowDatabase,password:tdbConn.password})}));_state.label=3;case 3:_state.trys.push([3,6,7,9]);return[4,sdb.migrate.latest()];case 4:_ref=_sliced_to_array.apply(void 0,[_state.sent(),2]),batchNo=_ref[0],applied=_ref[1];console.log(_chalk.default.green("Shadow DB 테스트에 성공했습니다!"),{batchNo:batchNo,applied:applied});console.log(_chalk.default.magenta("".concat(shadowDatabase," 삭제")));return[4,tdb.raw("DROP DATABASE IF EXISTS `".concat(shadowDatabase,"`;"))];case 5:_state.sent();return[2,[{connKey:"shadow",batchNo:batchNo,applied:applied}]];case 6:e=_state.sent();console.error(e);throw new _soexceptions.ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");case 7:return[4,tdb.destroy()];case 8:_state.sent();return[7];case 9:return[2]}})})()}},{key:"resetAll",value:function resetAll(){return _async_to_generator(function(){var answer,rollbackAllResult,migrationsDir;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,(0,_prompts.default)({type:"confirm",name:"value",message:"모든 DB를 롤백하고 전체 마이그레이션 파일을 삭제하시겠습니까?",initial:false})];case 1:answer=_state.sent();if(answer.value===false){return[2]}console.time(_chalk.default.red("rollback-all:"));return[4,Promise.all(this.targets.apply.map(function(db){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,db.migrate.forceFreeMigrationsLock()];case 1:_state.sent();return[2,db.migrate.rollback(undefined,true)]}})})()}))];case 2:rollbackAllResult=_state.sent();console.log({rollbackAllResult:rollbackAllResult});console.timeEnd(_chalk.default.red("rollback-all:"));migrationsDir="".concat(_api.Sonamu.apiRootPath,"/src/migrations");console.time(_chalk.default.red("delete migration files"));(0,_child_process.execSync)("rm -f ".concat(migrationsDir,"/*"));(0,_child_process.execSync)("rm -f ".concat(migrationsDir.replace("/src/","/dist/"),"/*"));console.timeEnd(_chalk.default.red("delete migration files"));return[2]}})}).call(this)}},{key:"compareMigrations",value:function compareMigrations(compareDB){return _async_to_generator(function(){var _this,entityIds,entitySetsWithJoinTable,joinTablesWithDup,joinTables,entitySets,codes;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;entityIds=_entitymanager.EntityManager.getAllIds();entitySetsWithJoinTable=entityIds.filter(function(entityId){var entity=_entitymanager.EntityManager.get(entityId);return entity.props.length>0}).map(function(entityId){var entity=_entitymanager.EntityManager.get(entityId);return _this.getMigrationSetFromEntity(entity)});joinTablesWithDup=entitySetsWithJoinTable.map(function(entitySet){return entitySet.joinTables}).flat();joinTables=Object.values(_lodash.default.groupBy(joinTablesWithDup,function(jt){return jt.table})).map(function(tables){if(tables.length===1){return tables[0]}return _object_spread_props(_object_spread({},tables[0]),{indexes:_lodash.default.uniqBy(tables.flatMap(function(t){return t.indexes}),function(index){return[index.type].concat(_to_consumable_array(index.columns.sort())).join("-")})})});entitySets=_to_consumable_array(entitySetsWithJoinTable).concat(_to_consumable_array(joinTables));return[4,Promise.all(entitySets.map(function(entitySet){return _async_to_generator(function(){var dbSet,_,_1,replaceColumnDefaultTo,entityColumns,dbColumns,entityIndexes,dbIndexes,replaceNoActionOnMySQL,entityForeigns,dbForeigns,droppingColumns,alterCodes,isEqualColumns,isEqualIndexes,_2,_3;return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,this.getMigrationSetFromDB(compareDB,entitySet.table)];case 1:dbSet=_state.sent();if(!(dbSet===null))return[3,4];return[4,this.generateCreateCode_ColumnAndIndexes(entitySet.table,entitySet.columns,entitySet.indexes)];case 2:_1=(_=[_state.sent()]).concat;return[4,this.generateCreateCode_Foreign(entitySet.table,entitySet.foreigns)];case 3:return[2,_1.apply(_,[_to_consumable_array.apply(void 0,[_state.sent()])])];case 4:replaceColumnDefaultTo=function(col){if(col.type==="float"&&col.defaultTo&&String(col.defaultTo).includes('"')===false){var _col_scale;col.defaultTo='"'.concat(Number(col.defaultTo).toFixed((_col_scale=col.scale)!==null&&_col_scale!==void 0?_col_scale:2),'"')}if(col.type==="string"&&col.defaultTo===""){col.defaultTo='""'}if(col.type==="boolean"&&col.defaultTo!==undefined){if(col.defaultTo==="0"||col.defaultTo==="false"){col.defaultTo="0"}else if(col.defaultTo==="1"||col.defaultTo==="true"){col.defaultTo="1"}}return col};entityColumns=_lodash.default.sortBy(entitySet.columns,function(a){return a.name}).map(replaceColumnDefaultTo);dbColumns=_lodash.default.sortBy(dbSet.columns,function(a){return a.name}).map(replaceColumnDefaultTo);entityIndexes=_lodash.default.sortBy(entitySet.indexes,function(a){return[a.type].concat(_to_consumable_array(a.columns.sort(function(c1,c2){return c1>c2?1:-1}))).join("-")});dbIndexes=_lodash.default.sortBy(dbSet.indexes,function(a){return[a.type].concat(_to_consumable_array(a.columns.sort(function(c1,c2){return c1>c2?1:-1}))).join("-")});replaceNoActionOnMySQL=function(f){var onDelete=f.onDelete,onUpdate=f.onUpdate;return _object_spread_props(_object_spread({},f),{onUpdate:onUpdate==="RESTRICT"?"NO ACTION":onUpdate,onDelete:onDelete==="RESTRICT"?"NO ACTION":onDelete})};entityForeigns=_lodash.default.sortBy(entitySet.foreigns,function(a){return[a.to].concat(_to_consumable_array(a.columns)).join("-")}).map(function(f){return replaceNoActionOnMySQL(f)});dbForeigns=_lodash.default.sortBy(dbSet.foreigns,function(a){return[a.to].concat(_to_consumable_array(a.columns)).join("-")}).map(function(f){return replaceNoActionOnMySQL(f)});droppingColumns=_lodash.default.differenceBy(dbColumns,entityColumns,function(col){return col.name});alterCodes=[];isEqualColumns=(0,_fastdeepequal.default)(entityColumns,dbColumns);isEqualIndexes=(0,_fastdeepequal.default)(entityIndexes.map(function(index){return _lodash.default.omit(index,["parser"])}),dbIndexes);if(!(!isEqualColumns||!isEqualIndexes))return[3,6];_2=alterCodes.push;return[4,this.generateAlterCode_ColumnAndIndexes(entitySet.table,entityColumns,entityIndexes,dbColumns,dbIndexes,dbSet.foreigns)];case 5:_2.apply(alterCodes,[_state.sent()]);_state.label=6;case 6:if(!((0,_fastdeepequal.default)(entityForeigns,dbForeigns)===false))return[3,8];_3=alterCodes.push;return[4,this.generateAlterCode_Foreigns(entitySet.table,entityForeigns,dbForeigns,droppingColumns)];case 7:_3.apply(alterCodes,[_state.sent()]);_state.label=8;case 8:if(alterCodes.every(function(alterCode){return alterCode===null})){return[2,null]}else{return[2,alterCodes.filter(function(alterCode){return alterCode!==null}).flat()]}return[2]}})}).call(_this)}))];case 1:codes=_state.sent().flat().filter(function(code){return code!==null});codes.sort(function(codeA,codeB){if(codeA.type==="foreign"&&codeB.type=="normal"){return 1}else if(codeA.type==="normal"&&codeB.type==="foreign"){return-1}else{return 0}});return[2,codes]}})}).call(this)}},{key:"getMigrationSetFromDB",value:function getMigrationSetFromDB(compareDB,table){return _async_to_generator(function(){var _this,dbColumns,dbIndexes,dbForeigns,ref,e,columns,dbIndexesGroup,parseIndexType,indexes,foreigns;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;_state.label=1;case 1:_state.trys.push([1,3,,4]);return[4,this.readTable(compareDB,table)];case 2:ref=_sliced_to_array.apply(void 0,[_state.sent(),3]),dbColumns=ref[0],dbIndexes=ref[1],dbForeigns=ref[2],ref;return[3,4];case 3:e=_state.sent();if((0,_types.isKnexError)(e)&&e.code==="ER_NO_SUCH_TABLE"){return[2,null]}console.error(e);return[2,null];case 4:columns=dbColumns.map(function(dbColumn){var dbColType=_this.resolveDBColType(dbColumn.Type,dbColumn.Field);return _object_spread({name:dbColumn.Field,nullable:dbColumn.Null!=="NO"},dbColType,function(){if(dbColumn.Default!==null){return{defaultTo:dbColumn.Default}}return{}}())});dbIndexesGroup=_lodash.default.groupBy(dbIndexes.filter(function(dbIndex){return dbIndex.Key_name!=="PRIMARY"&&!dbForeigns.find(function(dbForeign){return dbForeign.keyName===dbIndex.Key_name})}),function(dbIndex){return dbIndex.Key_name});parseIndexType=function(index){if(index.Index_type==="FULLTEXT"){return"fulltext"}return index.Non_unique===1?"index":"unique"};indexes=Object.keys(dbIndexesGroup).map(function(keyName){var currentIndexes=dbIndexesGroup[keyName];return{type:parseIndexType(currentIndexes[0]),columns:currentIndexes.map(function(currentIndex){return currentIndex.Column_name})}});foreigns=dbForeigns.map(function(dbForeign){return{columns:[dbForeign.from],to:"".concat(dbForeign.referencesTable,".").concat(dbForeign.referencesField),onUpdate:dbForeign.onUpdate,onDelete:dbForeign.onDelete}});return[2,{table:table,columns:columns,indexes:indexes,foreigns:foreigns}]}})}).call(this)}},{key:"resolveDBColType",value:function resolveDBColType(colType,colField){var _colType_split=_sliced_to_array(colType.split(" "),2),rawType=_colType_split[0],unsigned=_colType_split[1];var matched=rawType.match(/\(([0-9]+)\)/);var length;if(matched!==null&&matched[1]){rawType=rawType.replace(/\(([0-9]+)\)/,"");length=parseInt(matched[1])}if(rawType==="char"&&colField==="uuid"){return{type:"uuid"}}switch(rawType){case"int":return{type:"integer",unsigned:unsigned==="unsigned"};case"varchar":return _object_spread({type:"string"},length!==undefined&&{length:length});case"text":case"mediumtext":case"longtext":case"timestamp":case"json":case"date":case"time":return{type:rawType};case"datetime":return{type:"datetime"};case"tinyint":return{type:"boolean"};default:if(rawType.startsWith("decimal")){var _rawType_match;var _ref=_sliced_to_array((_rawType_match=rawType.match(/decimal\(([0-9]+),([0-9]+)\)/))!==null&&_rawType_match!==void 0?_rawType_match:[],3),precision=_ref[1],scale=_ref[2];return _object_spread({type:"decimal",precision:parseInt(precision),scale:parseInt(scale)},unsigned==="unsigned"&&{unsigned:true})}else if(rawType.startsWith("float")){var _rawType_match1;var _ref1=_sliced_to_array((_rawType_match1=rawType.match(/float\(([0-9]+),([0-9]+)\)/))!==null&&_rawType_match1!==void 0?_rawType_match1:[],3),precision1=_ref1[1],scale1=_ref1[2];return _object_spread({type:"float",precision:parseInt(precision1),scale:parseInt(scale1)},unsigned==="unsigned"&&{unsigned:true})}throw new Error("resolve 불가능한 DB컬럼 타입 ".concat(colType," ").concat(rawType))}}},{key:"readTable",value:function readTable(compareDB,tableName){return _async_to_generator(function(){var _ref,_cols,cols,_ref1,indexes,_ref2,_ref_,row,ddl,matched,foreignKeys,e;return _ts_generator(this,function(_state){switch(_state.label){case 0:_state.trys.push([0,4,,5]);return[4,compareDB.raw("SHOW FIELDS FROM ".concat(tableName))];case 1:_ref=_sliced_to_array.apply(void 0,[_state.sent(),1]),_cols=_ref[0];cols=_cols.map(function(col){return _object_spread({},col,col.Default!==null&&{Default:col.Default.replace(/[0-9]+/g,"").length>0&&col.Extra!=="DEFAULT_GENERATED"?'"'.concat(col.Default,'"'):col.Default})});return[4,compareDB.raw("SHOW INDEX FROM ".concat(tableName))];case 2:_ref1=_sliced_to_array.apply(void 0,[_state.sent(),1]),indexes=_ref1[0];return[4,compareDB.raw("SHOW CREATE TABLE ".concat(tableName))];case 3:_ref2=_sliced_to_array.apply(void 0,[_state.sent(),1]),_ref_=_sliced_to_array(_ref2[0],1),row=_ref_[0];ddl=row["Create Table"];matched=ddl.match(/CONSTRAINT .+/g);foreignKeys=(matched!==null&&matched!==void 0?matched:[]).map(function(line){var _replace_match_,_replace_match;var matched=line.match(/CONSTRAINT `(.+)` FOREIGN KEY \(`(.+)`\) REFERENCES `(.+)` \(`(.+)`\)( ON [A-Z ]+)*/);if(!matched){throw new Error("인식할 수 없는 FOREIGN KEY CONSTRAINT ".concat(line))}var _matched=_sliced_to_array(matched,6),keyName=_matched[1],from=_matched[2],referencesTable=_matched[3],referencesField=_matched[4],onClause=_matched[5];var _match;var _ref=_sliced_to_array((_match=(onClause!==null&&onClause!==void 0?onClause:"").match(/ON UPDATE ([A-Z ]+)$/))!==null&&_match!==void 0?_match:[],2),onUpdateFull=_ref[0],_onUpdate=_ref[1];var onUpdate=_onUpdate!==null&&_onUpdate!==void 0?_onUpdate:"NO ACTION";var _replace_match__trim;var onDelete=(_replace_match__trim=(_replace_match=(onClause!==null&&onClause!==void 0?onClause:"").replace(onUpdateFull!==null&&onUpdateFull!==void 0?onUpdateFull:"","").match(/ON DELETE ([A-Z ]+)/))===null||_replace_match===void 0?void 0:(_replace_match_=_replace_match[1])===null||_replace_match_===void 0?void 0:_replace_match_.trim())!==null&&_replace_match__trim!==void 0?_replace_match__trim:"NO ACTION";return{keyName:keyName,from:from,referencesTable:referencesTable,referencesField:referencesField,onDelete:onDelete,onUpdate:onUpdate}});return[2,[cols,indexes,foreignKeys]];case 4:e=_state.sent();throw e;case 5:return[2]}})})()}},{key:"getMigrationSetFromEntity",value:function getMigrationSetFromEntity(entity){var migrationSet=entity.props.reduce(function(r,prop){if((0,_types.isVirtualProp)(prop)){return r}if((0,_types.isHasManyRelationProp)(prop)){return r}if(!(0,_types.isRelationProp)(prop)){var type;if((0,_types.isTextProp)(prop)){type=prop.textType}else if((0,_types.isEnumProp)(prop)){type="string"}else{type=prop.type}var _prop_precision,_prop_scale;var column=_object_spread(_object_spread_props(_object_spread({name:prop.name,type:type},(0,_types.isIntegerProp)(prop)&&{unsigned:prop.unsigned===true},((0,_types.isStringProp)(prop)||(0,_types.isEnumProp)(prop))&&{length:prop.length}),{nullable:prop.nullable===true}),function(){if(prop.dbDefault!==undefined){return{defaultTo:prop.dbDefault}}return{}}(),((0,_types.isDecimalProp)(prop)||(0,_types.isFloatProp)(prop))&&{precision:(_prop_precision=prop.precision)!==null&&_prop_precision!==void 0?_prop_precision:8,scale:(_prop_scale=prop.scale)!==null&&_prop_scale!==void 0?_prop_scale:2});r.columns.push(column)}if((0,_types.isManyToManyRelationProp)(prop)){var relMd=_entitymanager.EntityManager.get(prop.with);var table1=entity.table;var table2=relMd.table;var join={from:"".concat(entity.table,".id"),through:{from:"".concat(prop.joinTable,".").concat(_inflection.default.singularize(table1),"_id"),to:"".concat(prop.joinTable,".").concat(_inflection.default.singularize(table2),"_id"),onUpdate:prop.onUpdate,onDelete:prop.onDelete},to:"".concat(relMd.table,".id")};var through=join.through;var fields=[through.from,through.to];r.joinTables.push({table:through.from.split(".")[0],indexes:[{type:"unique",columns:["uuid"]}].concat(_to_consumable_array(entity.indexes.filter(function(index){return index.columns.find(function(col){return col.includes(prop.joinTable+".")})}).map(function(index){return _object_spread_props(_object_spread({},index),{columns:index.columns.map(function(col){return col.replace(prop.joinTable+".","")})})}))),columns:[{name:"id",type:"integer",nullable:false,unsigned:true}].concat(_to_consumable_array(fields.map(function(field){return{name:field.split(".")[1],type:"integer",nullable:false,unsigned:true}})),[{name:"uuid",nullable:true,type:"uuid"}]),foreigns:fields.map(function(field){var col=field.split(".")[1];var to=function(){if(_inflection.default.singularize(join.to.split(".")[0])+"_id"===col){return join.to}else{return join.from}}();return{columns:[col],to:to,onUpdate:through.onUpdate,onDelete:through.onDelete}})});return r}else if((0,_types.isBelongsToOneRelationProp)(prop)||(0,_types.isOneToOneRelationProp)(prop)&&prop.hasJoinColumn){var idColumnName=prop.name+"_id";var _prop_nullable;r.columns.push({name:idColumnName,type:"integer",unsigned:true,nullable:(_prop_nullable=prop.nullable)!==null&&_prop_nullable!==void 0?_prop_nullable:false});var _prop_useConstraint;if(((_prop_useConstraint=prop.useConstraint)!==null&&_prop_useConstraint!==void 0?_prop_useConstraint:true)===true){var _prop_onUpdate,_prop_onDelete;r.foreigns.push({columns:[idColumnName],to:"".concat(_inflection.default.underscore(_inflection.default.pluralize(prop.with)).toLowerCase(),".id"),onUpdate:(_prop_onUpdate=prop.onUpdate)!==null&&_prop_onUpdate!==void 0?_prop_onUpdate:"RESTRICT",onDelete:(_prop_onDelete=prop.onDelete)!==null&&_prop_onDelete!==void 0?_prop_onDelete:"RESTRICT"})}}return r},{table:entity.table,columns:[],indexes:[],foreigns:[],joinTables:[]});migrationSet.indexes=entity.indexes.filter(function(index){return index.columns.find(function(col){return col.includes(".")===false})});migrationSet.columns=migrationSet.columns.concat({name:"uuid",nullable:true,type:"uuid"});migrationSet.indexes=migrationSet.indexes.concat({type:"unique",columns:["uuid"]});return migrationSet}},{key:"genColumnDefinitions",value:function genColumnDefinitions(columns){return columns.map(function(column){var chains=[];if(column.name==="id"){return"table.increments().primary();"}if(column.type==="float"||column.type==="decimal"){chains.push("".concat(column.type,"('").concat(column.name,"', ").concat(column.precision,", ").concat(column.scale,")"))}else{var columnType=column.type;var extraType;if(columnType.includes("text")&&columnType!=="text"){extraType=columnType;columnType="text"}chains.push("".concat(column.type,"('").concat(column.name,"'").concat(column.length?", ".concat(column.length):"").concat(extraType?", '".concat(extraType,"'"):"",")"))}if(column.unsigned){chains.push("unsigned()")}chains.push(column.nullable?"nullable()":"notNullable()");if(column.defaultTo!==undefined){if(typeof column.defaultTo==="string"&&column.defaultTo.startsWith('"')){chains.push("defaultTo(".concat(column.defaultTo,")"))}else{chains.push("defaultTo(knex.raw('".concat(column.defaultTo,"'))"))}}return"table.".concat(chains.join("."),";")})}},{key:"genIndexDefinitions",value:function genIndexDefinitions(indexes){if(indexes.length===0){return[]}var methodMap={index:"index",fulltext:"index",unique:"unique"};var lines=_lodash.default.uniq(indexes.reduce(function(r,index){r.push("table.".concat(methodMap[index.type],"([").concat(index.columns.map(function(col){return"'".concat(col,"'")}).join(","),"], ").concat(index.type==="fulltext"?"undefined, { indexType: 'FULLTEXT' }":"",")"));return r},[]));return lines}},{key:"genForeignDefinitions",value:function genForeignDefinitions(table,foreigns){return foreigns.reduce(function(r,foreign){var columnsStringQuote=foreign.columns.map(function(col){return"'".concat(col.replace("".concat(table,"."),""),"'")}).join(",");r.up.push("table.foreign('".concat(foreign.columns.join(","),"')\n .references('").concat(foreign.to,"')\n .onUpdate('").concat(foreign.onUpdate,"')\n .onDelete('").concat(foreign.onDelete,"')"));r.down.push("table.dropForeign([".concat(columnsStringQuote,"])"));return r},{up:[],down:[]})}},{key:"generateCreateCode_ColumnAndIndexes",value:function generateCreateCode_ColumnAndIndexes(table,columns,indexes){return _async_to_generator(function(){var _this,__partition,ngramIndexes,standardIndexes,lines,_tmp;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;__partition=_sliced_to_array(_lodash.default.partition(indexes,function(i){return i.type==="fulltext"&&i.parser==="ngram"}),2),ngramIndexes=__partition[0],standardIndexes=__partition[1];lines=['import { Knex } from "knex";',"","export async function up(knex: Knex): Promise<void> {",'await knex.schema.createTable("'.concat(table,'", (table) => {'),"// columns"].concat(_to_consumable_array(this.genColumnDefinitions(columns)),["","// indexes"],_to_consumable_array(standardIndexes.map(function(index){return _this.genIndexDefinition(index,table)})),["});"],_to_consumable_array(ngramIndexes.map(function(index){return _this.genIndexDefinition(index,table)})),["}","","export async function down(knex: Knex): Promise<void> {",' return knex.schema.dropTable("'.concat(table,'");'),"}"]);_tmp={table:table,type:"normal",title:"create__".concat(table)};return[4,_prettier.default.format(lines.join("\n"),{parser:"typescript"})];case 1:return[2,(_tmp.formatted=_state.sent(),_tmp)]}})}).call(this)}},{key:"generateCreateCode_Foreign",value:function generateCreateCode_Foreign(table,foreigns){return _async_to_generator(function(){var _this_genForeignDefinitions,up,down,lines,foreignKeysString,_tmp;return _ts_generator(this,function(_state){switch(_state.label){case 0:if(foreigns.length===0){return[2,[]]}_this_genForeignDefinitions=this.genForeignDefinitions(table,foreigns),up=_this_genForeignDefinitions.up,down=_this_genForeignDefinitions.down;if(up.length===0&&down.length===0){console.log("fk 가 뭔가 다릅니다");return[2,[]]}lines=['import { Knex } from "knex";',"","export async function up(knex: Knex): Promise<void> {",'return knex.schema.alterTable("'.concat(table,'", (table) => {'),"// create fk"].concat(_to_consumable_array(up),["});","}","","export async function down(knex: Knex): Promise<void> {",'return knex.schema.alterTable("'.concat(table,'", (table) => {'),"// drop fk"],_to_consumable_array(down),["});","}"]);foreignKeysString=foreigns.map(function(foreign){return foreign.columns.join("_")}).join("_");_tmp={table:table,type:"foreign",title:"foreign__".concat(table,"__").concat(foreignKeysString)};return[4,_prettier.default.format(lines.join("\n"),{parser:"typescript"})];case 1:return[2,[(_tmp.formatted=_state.sent(),_tmp)]]}})}).call(this)}},{key:"showMigrationSet",value:function showMigrationSet(which,migrationSet){var columns=migrationSet.columns,indexes=migrationSet.indexes,foreigns=migrationSet.foreigns;var styledChalk=which==="Entity"?_chalk.default.bgGreen.black:_chalk.default.bgBlue.black;console.log(styledChalk("".concat(which," ").concat(migrationSet.table," Columns ")));console.table(columns.map(function(column){return _object_spread({},_lodash.default.pick(column,["name","type","nullable","unsigned","length","defaultTo","precision","scale"]))}),["name","type","nullable","unsigned","length","defaultTo","precision","scale"]);if(indexes.length>0){console.log(styledChalk("".concat(which," ").concat(migrationSet.table," Indexes ")));console.table(indexes.map(function(index){return _object_spread({},_lodash.default.pick(index,["type","columns","name"]))}))}if(foreigns.length>0){console.log(_chalk.default.bgMagenta.black("".concat(which," ").concat(migrationSet.table," Foreigns ")));console.table(foreigns.map(function(foreign){return _object_spread({},_lodash.default.pick(foreign,["columns","to","onUpdate","onDelete"]))}))}}},{key:"generateAlterCode_ColumnAndIndexes",value:function generateAlterCode_ColumnAndIndexes(table,entityColumns,entityIndexes,dbColumns,dbIndexes,dbForeigns){return _async_to_generator(function(){var _this,alterColumnsTo,alterColumnLinesTo,alterIndexesTo,__partition,ngramIndexes,standardIndexes,indexNeedsToDrop,lines,formatted,title;return _ts_generator(this,function(_state){switch(_state.label){case 0:_this=this;alterColumnsTo=this.getAlterColumnsTo(entityColumns,dbColumns);alterColumnLinesTo=this.getAlterColumnLinesTo(alterColumnsTo,entityColumns,table,dbForeigns);alterIndexesTo=this.getAlterIndexesTo(entityIndexes,dbIndexes);__partition=_sliced_to_array(_lodash.default.partition(alterIndexesTo.add,function(i){return i.type==="fulltext"&&i.parser==="ngram"}),2),ngramIndexes=__partition[0],standardIndexes=__partition[1];indexNeedsToDrop=alterIndexesTo.drop.filter(function(index){return index.columns.every(function(colName){return alterColumnsTo.drop.map(function(col){return col.name}).includes(colName)})===false});lines=['import { Knex } from "knex";',"","export async function up(knex: Knex): Promise<void> {",'await knex.schema.alterTable("'.concat(table,'", (table) => {')].concat(_to_consumable_array(alterColumnsTo.add.length>0?alterColumnLinesTo.add.up:[]),_to_consumable_array(alterColumnsTo.drop.length>0?alterColumnLinesTo.drop.up:[]),_to_consumable_array(alterColumnsTo.alter.length>0?alterColumnLinesTo.alter.up:[]),_to_consumable_array(standardIndexes.map(function(index){return _this.genIndexDefinition(index,table)})),_to_consumable_array(indexNeedsToDrop.map(this.genIndexDropDefinition)),["});"],_to_consumable_array(ngramIndexes.map(function(index){return _this.genIndexDefinition(index,table)})),["}","","export async function down(knex: Knex): Promise<void> {",'return knex.schema.alterTable("'.concat(table,'", (table) => {')],_to_consumable_array(alterColumnsTo.add.length>0?alterColumnLinesTo.add.down:[]),_to_consumable_array(alterColumnsTo.drop.length>0?alterColumnLinesTo.drop.down:[]),_to_consumable_array(alterColumnsTo.alter.length>0?alterColumnLinesTo.alter.down:[]),_to_consumable_array(alterIndexesTo.add.filter(function(index){return index.columns.every(function(colName){return alterColumnsTo.add.map(function(col){return col.name}).includes(colName)})===false}).map(this.genIndexDropDefinition)),_to_consumable_array(indexNeedsToDrop.map(function(index){return _this.genIndexDefinition(index,table)})),["});","}"]);return[4,_prettier.default.format(lines.join("\n"),{parser:"typescript"})];case 1:formatted=_state.sent();title=["alter",table].concat(_to_consumable_array(["add","drop","alter"].map(function(action){var len=alterColumnsTo[action].length;if(len>0){return action+len}return null}).filter(function(part){return part!==null}))).join("_");return[2,[{table:table,title:title,formatted:formatted,type:"normal"}]]}})}).call(this)}},{key:"getAlterColumnsTo",value:function getAlterColumnsTo(entityColumns,dbColumns){var columnsTo={add:[],drop:[],alter:[]};var extraColumns={db:_lodash.default.differenceBy(dbColumns,entityColumns,function(col){return col.name}),entity:_lodash.default.differenceBy(entityColumns,dbColumns,function(col){return col.name})};if(extraColumns.entity.length>0){columnsTo.add=columnsTo.add.concat(extraColumns.entity)}if(extraColumns.db.length>0){columnsTo.drop=columnsTo.drop.concat(extraColumns.db)}var sameDbColumns=_lodash.default.intersectionBy(dbColumns,entityColumns,function(col){return col.name});var sameMdColumns=_lodash.default.intersectionBy(entityColumns,dbColumns,function(col){return col.name});columnsTo.alter=_lodash.default.differenceWith(sameDbColumns,sameMdColumns,function(a,b){return(0,_fastdeepequal.default)(a,b)});return columnsTo}},{key:"getAlterColumnLinesTo",value:function getAlterColumnLinesTo(columnsTo,entityColumns,table,dbForeigns){var _this=this;var linesTo={add:{up:[],down:[]},drop:{up:[],down:[]},alter:{up:[],down:[]}};linesTo.add={up:["// add"].concat(_to_consumable_array(this.genColumnDefinitions(columnsTo.add))),down:["// rollback - add","table.dropColumns(".concat(columnsTo.add.map(function(col){return"'".concat(col.name,"'")}).join(", "),")")]};var dropColumnNames=columnsTo.drop.map(function(col){return col.name});var fkToDropBeforeColumn=dbForeigns.filter(function(fk){return fk.columns.some(function(col){return dropColumnNames.includes(col)})});var dropFkLines=fkToDropBeforeColumn.map(function(fk){var columnsStringQuote=fk.columns.map(function(col){return"'".concat(col,"'")}).join(",");return"table.dropForeign([".concat(columnsStringQuote,"])")});var restoreFkLines=this.genForeignDefinitions(table,fkToDropBeforeColumn).up;linesTo.drop={up:_to_consumable_array(dropFkLines.length>0?["// drop foreign keys on columns to be dropped"].concat(_to_consumable_array(dropFkLines)):[]).concat(["// drop columns","table.dropColumns(".concat(columnsTo.drop.map(function(col){return"'".concat(col.name,"'")}).join(", "),")")]),down:["// rollback - drop columns"].concat(_to_consumable_array(this.genColumnDefinitions(columnsTo.drop)),_to_consumable_array(restoreFkLines.length>0?["// restore foreign keys"].concat(_to_consumable_array(restoreFkLines)):[]))};linesTo.alter=columnsTo.alter.reduce(function(r,dbColumn){var entityColumn=entityColumns.find(function(col){return col.name==dbColumn.name});if(entityColumn===undefined){return r}var columnDiffUp=_lodash.default.difference(_this.genColumnDefinitions([entityColumn]),_this.genColumnDefinitions([dbColumn]));var columnDiffDown=_lodash.default.difference(_this.genColumnDefinitions([dbColumn]),_this.genColumnDefinitions([entityColumn]));if(columnDiffUp.length>0){r.up=_to_consumable_array(r.up).concat(["// alter column"],_to_consumable_array(columnDiffUp.map(function(l){return l.replace(";","")+".alter();"})));r.down=_to_consumable_array(r.down).concat(["// rollback - alter column"],_to_consumable_array(columnDiffDown.map(function(l){return l.replace(";","")+".alter();"})))}return r},{up:[],down:[]});return linesTo}},{key:"getAlterIndexesTo",value:function getAlterIndexesTo(entityIndexes,dbIndexes){var indexesTo={add:[],drop:[]};var extraIndexes={db:_lodash.default.differenceBy(dbIndexes,entityIndexes,function(col){return[col.type,col.columns.join("-")].join("//")}),entity:_lodash.default.differenceBy(entityIndexes,dbIndexes,function(col){return[col.type,col.columns.join("-")].join("//")})};if(extraIndexes.entity.length>0){indexesTo.add=indexesTo.add.concat(extraIndexes.entity)}if(extraIndexes.db.length>0){indexesTo.drop=indexesTo.drop.concat(extraIndexes.db)}return indexesTo}},{key:"genIndexDefinition",value:function genIndexDefinition(index,table){var methodMap={index:"index",fulltext:"index",unique:"unique"};if(index.type==="fulltext"&&index.parser==="ngram"){var indexName="".concat(table,"_").concat(index.columns.join("_"),"_index");return"await knex.raw(`ALTER TABLE ".concat(table," ADD FULLTEXT INDEX ").concat(indexName," (").concat(index.columns.join(", "),") WITH PARSER ngram`);")}return"table.".concat(methodMap[index.type],"([").concat(index.columns.map(function(col){return"'".concat(col,"'")}).join(","),"]").concat(index.type==="fulltext"?", undefined, 'FULLTEXT'":"",")")}},{key:"genIndexDropDefinition",value:function genIndexDropDefinition(index){var methodMap={index:"Index",fulltext:"Index",unique:"Unique"};return"table.drop".concat(methodMap[index.type],"([").concat(index.columns.map(function(columnName){return"'".concat(columnName,"'")}).join(","),"])")}},{key:"generateAlterCode_Foreigns",value:function generateAlterCode_Foreigns(_0,_1,_2){return _async_to_generator(function(table,entityForeigns,dbForeigns){var droppingColumns,getKey,droppingColumnNames,fkTo,linesTo,hasLines,lines,formatted,title;var _arguments=arguments;return _ts_generator(this,function(_state){switch(_state.label){case 0:droppingColumns=_arguments.length>3&&_arguments[3]!==void 0?_arguments[3]:[];getKey=function(mf){return[mf.columns.join("-"),mf.to].join("///")};droppingColumnNames=droppingColumns.map(function(col){return col.name});fkTo=entityForeigns.reduce(function(result,entityF){var matchingDbF=dbForeigns.find(function(dbF){return getKey(entityF)===getKey(dbF)});if(!matchingDbF){result.add.push(entityF);return result}if((0,_fastdeepequal.default)(entityF,matchingDbF)===false){result.alterSrc.push(matchingDbF);result.alterDst.push(entityF);return result}return result},{add:[],drop:[],alterSrc:[],alterDst:[]});dbForeigns.forEach(function(dbF){var matchingEntityF=entityForeigns.find(function(entityF){return getKey(entityF)===getKey(dbF)});if(!matchingEntityF){var isColumnDropping=dbF.columns.some(function(col){return droppingColumnNames.includes(col)});if(!isColumnDropping){fkTo.drop.push(dbF)}}});linesTo={add:this.genForeignDefinitions(table,fkTo.add),drop:this.genForeignDefinitions(table,fkTo.drop),alterSrc:this.genForeignDefinitions(table,fkTo.alterSrc),alterDst:this.genForeignDefinitions(table,fkTo.alterDst)};hasLines=Object.values(linesTo).some(function(l){return l.up.length>0||l.down.length>0});if(!hasLines){return[2,[]]}lines=['import { Knex } from "knex";',"","export async function up(knex: Knex): Promise<void> {",'return knex.schema.alterTable("'.concat(table,'", (table) => {')].concat(_to_consumable_array(linesTo.drop.down),_to_consumable_array(linesTo.add.up),_to_consumable_array(linesTo.alterSrc.down),_to_consumable_array(linesTo.alterDst.up),["})","}","","export async function down(knex: Knex): Promise<void> {",'return knex.schema.alterTable("'.concat(table,'", (table) => {')],_to_consumable_array(linesTo.add.down),_to_consumable_array(linesTo.alterDst.down),_to_consumable_array(linesTo.alterSrc.up),_to_consumable_array(linesTo.drop.up),["})","}"]);return[4,_prettier.default.format(lines.join("\n"),{parser:"typescript"})];case 1:formatted=_state.sent();title=["alter",table,"foreigns"].join("_");return[2,[{table:table,title:title,formatted:formatted,type:"normal"}]]}})}).apply(this,arguments)}},{key:"destroy",value:function destroy(){return _async_to_generator(function(){return _ts_generator(this,function(_state){switch(_state.label){case 0:return[4,Promise.all(this.targets.apply.map(function(db){return db.destroy()}))];case 1:_state.sent();return[2]}})}).call(this)}}]);return Migrator}();
2
- //# sourceMappingURL=migrator.js.map
@@ -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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"}