sonamu 0.0.42 → 0.1.0
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.
- package/.pnp.cjs +1963 -951
- package/.pnp.loader.mjs +1816 -54
- package/.yarnrc.yml +1 -1
- package/dist/api/code-converters.d.ts +3 -3
- package/dist/api/code-converters.d.ts.map +1 -1
- package/dist/api/code-converters.js +5 -15
- package/dist/api/code-converters.js.map +1 -1
- package/dist/api/context.d.ts +1 -1
- package/dist/api/context.d.ts.map +1 -1
- package/dist/api/decorators.d.ts +3 -3
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/sonamu.d.ts +3 -3
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +6 -6
- package/dist/api/sonamu.js.map +1 -1
- package/dist/bin/cli.js +132 -33
- package/dist/bin/cli.js.map +1 -1
- package/dist/database/db.d.ts +2 -2
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +1 -1
- package/dist/database/db.js.map +1 -1
- package/dist/database/upsert-builder.d.ts +2 -2
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +10 -8
- package/dist/database/upsert-builder.js.map +1 -1
- package/dist/entity/entity-manager.d.ts +29 -0
- package/dist/entity/entity-manager.d.ts.map +1 -0
- package/dist/entity/entity-manager.js +128 -0
- package/dist/entity/entity-manager.js.map +1 -0
- package/dist/entity/entity-utils.d.ts +61 -0
- package/dist/entity/entity-utils.d.ts.map +1 -0
- package/dist/entity/entity-utils.js +121 -0
- package/dist/entity/entity-utils.js.map +1 -0
- package/dist/entity/entity.d.ts +49 -0
- package/dist/entity/entity.d.ts.map +1 -0
- package/dist/entity/entity.js +504 -0
- package/dist/entity/entity.js.map +1 -0
- package/dist/entity/migrator.d.ts +143 -0
- package/dist/entity/migrator.d.ts.map +1 -0
- package/dist/entity/migrator.js +1385 -0
- package/dist/entity/migrator.js.map +1 -0
- package/dist/entity/smd-utils.d.ts +61 -0
- package/dist/entity/smd-utils.d.ts.map +1 -0
- package/dist/entity/smd-utils.js +121 -0
- package/dist/entity/smd-utils.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/smd/entity-manager.d.ts +28 -0
- package/dist/smd/entity-manager.d.ts.map +1 -0
- package/dist/smd/entity-manager.js +119 -0
- package/dist/smd/entity-manager.js.map +1 -0
- package/dist/smd/entity.d.ts +40 -0
- package/dist/smd/entity.d.ts.map +1 -0
- package/dist/smd/entity.js +430 -0
- package/dist/smd/entity.js.map +1 -0
- package/dist/smd/migrator.d.ts +2 -2
- package/dist/smd/migrator.d.ts.map +1 -1
- package/dist/smd/migrator.js +5 -5
- package/dist/smd/migrator.js.map +1 -1
- package/dist/smd/smd-manager.d.ts +3 -3
- package/dist/smd/smd-manager.d.ts.map +1 -1
- package/dist/smd/smd-manager.js +2 -2
- package/dist/smd/smd-manager.js.map +1 -1
- package/dist/smd/smd-utils.d.ts +3 -3
- package/dist/smd/smd-utils.d.ts.map +1 -1
- package/dist/smd/smd.d.ts +5 -6
- package/dist/smd/smd.d.ts.map +1 -1
- package/dist/smd/smd.js +3 -3
- package/dist/smd/smd.js.map +1 -1
- package/dist/syncer/syncer.d.ts +15 -11
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +134 -74
- package/dist/syncer/syncer.js.map +1 -1
- package/dist/templates/base-template.d.ts +2 -2
- package/dist/templates/base-template.d.ts.map +1 -1
- package/dist/templates/entity.template.d.ts +17 -0
- package/dist/templates/entity.template.d.ts.map +1 -0
- package/dist/templates/entity.template.js +46 -0
- package/dist/templates/entity.template.js.map +1 -0
- package/dist/templates/generated.template.d.ts +11 -7
- package/dist/templates/generated.template.d.ts.map +1 -1
- package/dist/templates/generated.template.js +72 -43
- package/dist/templates/generated.template.js.map +1 -1
- package/dist/templates/generated_http.template.d.ts +3 -3
- package/dist/templates/generated_http.template.d.ts.map +1 -1
- package/dist/templates/generated_http.template.js +3 -3
- package/dist/templates/generated_http.template.js.map +1 -1
- package/dist/templates/init_enums.template.d.ts +2 -2
- package/dist/templates/init_enums.template.d.ts.map +1 -1
- package/dist/templates/init_enums.template.js +2 -2
- package/dist/templates/init_enums.template.js.map +1 -1
- package/dist/templates/init_generated.template.d.ts +3 -3
- package/dist/templates/init_generated.template.d.ts.map +1 -1
- package/dist/templates/init_generated.template.js +13 -14
- package/dist/templates/init_generated.template.js.map +1 -1
- package/dist/templates/init_types.template.d.ts +3 -3
- package/dist/templates/init_types.template.d.ts.map +1 -1
- package/dist/templates/init_types.template.js +10 -10
- package/dist/templates/init_types.template.js.map +1 -1
- package/dist/templates/model.template.d.ts +3 -3
- package/dist/templates/model.template.d.ts.map +1 -1
- package/dist/templates/model.template.js +28 -28
- package/dist/templates/model.template.js.map +1 -1
- package/dist/templates/model_test.template.d.ts +3 -3
- package/dist/templates/model_test.template.d.ts.map +1 -1
- package/dist/templates/model_test.template.js +4 -4
- package/dist/templates/model_test.template.js.map +1 -1
- package/dist/templates/service.template.d.ts +3 -3
- package/dist/templates/service.template.d.ts.map +1 -1
- package/dist/templates/service.template.js +3 -3
- package/dist/templates/service.template.js.map +1 -1
- package/dist/templates/smd.template.d.ts +2 -2
- package/dist/templates/smd.template.d.ts.map +1 -1
- package/dist/templates/smd.template.js +2 -2
- package/dist/templates/smd.template.js.map +1 -1
- package/dist/templates/view_enums_buttonset.template.d.ts +3 -3
- package/dist/templates/view_enums_buttonset.template.d.ts.map +1 -1
- package/dist/templates/view_enums_buttonset.template.js +4 -4
- package/dist/templates/view_enums_buttonset.template.js.map +1 -1
- package/dist/templates/view_enums_dropdown.template.d.ts +3 -3
- package/dist/templates/view_enums_dropdown.template.d.ts.map +1 -1
- package/dist/templates/view_enums_dropdown.template.js +3 -3
- package/dist/templates/view_enums_dropdown.template.js.map +1 -1
- package/dist/templates/view_enums_select.template.d.ts +3 -3
- package/dist/templates/view_enums_select.template.d.ts.map +1 -1
- package/dist/templates/view_enums_select.template.js +3 -3
- package/dist/templates/view_enums_select.template.js.map +1 -1
- package/dist/templates/view_form.template.d.ts +25 -29
- package/dist/templates/view_form.template.d.ts.map +1 -1
- package/dist/templates/view_form.template.js +19 -19
- package/dist/templates/view_form.template.js.map +1 -1
- package/dist/templates/view_id_all_select.template.d.ts +3 -3
- package/dist/templates/view_id_all_select.template.d.ts.map +1 -1
- package/dist/templates/view_id_all_select.template.js +4 -4
- package/dist/templates/view_id_all_select.template.js.map +1 -1
- package/dist/templates/view_id_async_select.template.d.ts +3 -3
- package/dist/templates/view_id_async_select.template.d.ts.map +1 -1
- package/dist/templates/view_id_async_select.template.js +6 -6
- package/dist/templates/view_id_async_select.template.js.map +1 -1
- package/dist/templates/view_list.template.d.ts +30 -34
- package/dist/templates/view_list.template.d.ts.map +1 -1
- package/dist/templates/view_list.template.js +40 -40
- package/dist/templates/view_list.template.js.map +1 -1
- package/dist/templates/view_list_columns.template.d.ts +3 -3
- package/dist/templates/view_list_columns.template.d.ts.map +1 -1
- package/dist/templates/view_list_columns.template.js +3 -3
- package/dist/templates/view_list_columns.template.js.map +1 -1
- package/dist/templates/view_search_input.template.d.ts +3 -3
- package/dist/templates/view_search_input.template.d.ts.map +1 -1
- package/dist/templates/view_search_input.template.js +3 -3
- package/dist/templates/view_search_input.template.js.map +1 -1
- package/dist/testing/fixture-manager.d.ts +2 -2
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +18 -16
- package/dist/testing/fixture-manager.js.map +1 -1
- package/dist/types/smd.types.d.ts +741 -0
- package/dist/types/smd.types.d.ts.map +1 -0
- package/dist/types/smd.types.js +292 -0
- package/dist/types/smd.types.js.map +1 -0
- package/dist/types/types.d.ts +185 -188
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +22 -30
- package/dist/types/types.js.map +1 -1
- package/dist/utils/model.d.ts +2 -2
- package/dist/utils/model.d.ts.map +1 -1
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +6 -2
- package/dist/utils/utils.js.map +1 -1
- package/package.json +11 -8
- package/src/api/code-converters.ts +9 -17
- package/src/api/sonamu.ts +10 -6
- package/src/bin/cli.ts +156 -27
- package/src/database/upsert-builder.ts +2 -2
- package/src/entity/entity-manager.ts +150 -0
- package/src/{smd/smd-utils.ts → entity/entity-utils.ts} +3 -3
- package/src/entity/entity.ts +666 -0
- package/src/{smd → entity}/migrator.ts +426 -106
- package/src/index.ts +3 -3
- package/src/smd/smd-manager.ts +3 -13
- package/src/smd/smd.ts +13 -10
- package/src/syncer/syncer.ts +125 -73
- package/src/templates/base-template.ts +2 -2
- package/src/templates/entity.template.ts +50 -0
- package/src/templates/generated.template.ts +93 -57
- package/src/templates/generated_http.template.ts +4 -4
- package/src/templates/init_types.template.ts +11 -11
- package/src/templates/model.template.ts +29 -29
- package/src/templates/model_test.template.ts +5 -5
- package/src/templates/service.template.ts +4 -4
- package/src/templates/view_enums_buttonset.template.ts +5 -5
- package/src/templates/view_enums_dropdown.template.ts +4 -4
- package/src/templates/view_enums_select.template.ts +8 -4
- package/src/templates/view_form.template.ts +21 -21
- package/src/templates/view_id_all_select.template.ts +5 -5
- package/src/templates/view_id_async_select.template.ts +9 -7
- package/src/templates/view_list.template.ts +54 -44
- package/src/templates/view_list_columns.template.ts +4 -4
- package/src/templates/view_search_input.template.ts +4 -4
- package/src/testing/fixture-manager.ts +12 -12
- package/src/types/types.ts +59 -39
- package/src/utils/utils.ts +4 -0
- package/tsconfig.json +4 -1
- package/src/templates/init_enums.template.ts +0 -71
- package/src/templates/init_generated.template.ts +0 -51
- package/src/templates/smd.template.ts +0 -53
|
@@ -3,9 +3,11 @@ import _, {
|
|
|
3
3
|
differenceBy,
|
|
4
4
|
differenceWith,
|
|
5
5
|
groupBy,
|
|
6
|
+
intersection,
|
|
6
7
|
intersectionBy,
|
|
7
8
|
pick,
|
|
8
9
|
sortBy,
|
|
10
|
+
sum,
|
|
9
11
|
uniq,
|
|
10
12
|
uniqBy,
|
|
11
13
|
} from "lodash";
|
|
@@ -51,14 +53,34 @@ import {
|
|
|
51
53
|
RelationOn,
|
|
52
54
|
} from "../types/types";
|
|
53
55
|
import { propIf } from "../utils/lodash-able";
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
56
|
+
import { EntityManager } from "./entity-manager";
|
|
57
|
+
import { Entity } from "./entity";
|
|
56
58
|
import { Sonamu } from "../api";
|
|
59
|
+
import { ServiceUnavailableException } from "../exceptions/so-exceptions";
|
|
60
|
+
import { nonNullable } from "../utils/utils";
|
|
57
61
|
|
|
58
62
|
type MigratorMode = "dev" | "deploy";
|
|
59
63
|
export type MigratorOptions = {
|
|
60
64
|
readonly mode: MigratorMode;
|
|
61
65
|
};
|
|
66
|
+
type MigrationCode = {
|
|
67
|
+
name: string;
|
|
68
|
+
path: string;
|
|
69
|
+
};
|
|
70
|
+
type ConnString = `${"mysql2"}://${string}@${string}:${number}/${string}`; // mysql2://account@host:port/database
|
|
71
|
+
export type MigrationStatus = {
|
|
72
|
+
codes: MigrationCode[];
|
|
73
|
+
conns: {
|
|
74
|
+
name: string;
|
|
75
|
+
connKey: string;
|
|
76
|
+
connString: ConnString;
|
|
77
|
+
currentVersion: string;
|
|
78
|
+
status: string | number;
|
|
79
|
+
pending: string[];
|
|
80
|
+
}[];
|
|
81
|
+
preparedCodes: GenMigrationCode[];
|
|
82
|
+
};
|
|
83
|
+
|
|
62
84
|
export class Migrator {
|
|
63
85
|
readonly mode: MigratorMode;
|
|
64
86
|
|
|
@@ -108,6 +130,279 @@ export class Migrator {
|
|
|
108
130
|
}
|
|
109
131
|
}
|
|
110
132
|
|
|
133
|
+
async getMigrationCodes(): Promise<{
|
|
134
|
+
normal: MigrationCode[];
|
|
135
|
+
onlyTs: MigrationCode[];
|
|
136
|
+
onlyJs: MigrationCode[];
|
|
137
|
+
}> {
|
|
138
|
+
const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
139
|
+
const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;
|
|
140
|
+
const srcMigrations = readdirSync(srcMigrationsDir)
|
|
141
|
+
.filter((f) => f.endsWith(".ts"))
|
|
142
|
+
.map((f) => f.split(".")[0]);
|
|
143
|
+
const distMigrations = readdirSync(distMigrationsDir)
|
|
144
|
+
.filter((f) => f.endsWith(".js"))
|
|
145
|
+
.map((f) => f.split(".")[0]);
|
|
146
|
+
|
|
147
|
+
const normal = intersection(srcMigrations, distMigrations)
|
|
148
|
+
.map((filename) => {
|
|
149
|
+
return {
|
|
150
|
+
name: filename,
|
|
151
|
+
path: path.join(srcMigrationsDir, filename) + ".ts",
|
|
152
|
+
};
|
|
153
|
+
})
|
|
154
|
+
.sort((a, b) => (a > b ? 1 : -1));
|
|
155
|
+
|
|
156
|
+
const onlyTs = difference(srcMigrations, distMigrations).map((filename) => {
|
|
157
|
+
return {
|
|
158
|
+
name: filename,
|
|
159
|
+
path: path.join(srcMigrationsDir, filename) + ".ts",
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const onlyJs = difference(distMigrations, srcMigrations).map((filename) => {
|
|
164
|
+
return {
|
|
165
|
+
name: filename,
|
|
166
|
+
path: path.join(distMigrationsDir, filename) + ".js",
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
normal,
|
|
172
|
+
onlyTs,
|
|
173
|
+
onlyJs,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async getStatus(): Promise<MigrationStatus> {
|
|
178
|
+
const { normal, onlyTs, onlyJs } = await this.getMigrationCodes();
|
|
179
|
+
if (onlyTs.length > 0) {
|
|
180
|
+
console.debug({ onlyTs });
|
|
181
|
+
throw new ServiceUnavailableException(
|
|
182
|
+
`There is an un-compiled TS migration files.\nPlease run the dev:serve\n\n${onlyTs
|
|
183
|
+
.map((f) => f.name)
|
|
184
|
+
.join("\n")}`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
if (onlyJs.length > 0) {
|
|
188
|
+
console.debug({ onlyJs });
|
|
189
|
+
await Promise.all(
|
|
190
|
+
onlyJs.map(async (f) => {
|
|
191
|
+
execSync(
|
|
192
|
+
`rm -f ${f.path.replace("/src/", "/dist/").replace(".ts", ".js")}`
|
|
193
|
+
);
|
|
194
|
+
})
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const connKeys = Object.keys(Sonamu.dbConfig).filter(
|
|
199
|
+
(key) => key.endsWith("_slave") === false
|
|
200
|
+
) as (keyof typeof Sonamu.dbConfig)[];
|
|
201
|
+
|
|
202
|
+
const statuses = await Promise.all(
|
|
203
|
+
connKeys.map(async (connKey) => {
|
|
204
|
+
const knexOptions = Sonamu.dbConfig[connKey];
|
|
205
|
+
const tConn = knex(knexOptions);
|
|
206
|
+
const status = await (async () => {
|
|
207
|
+
try {
|
|
208
|
+
return tConn.migrate.status();
|
|
209
|
+
} catch (err) {
|
|
210
|
+
return "error";
|
|
211
|
+
}
|
|
212
|
+
})();
|
|
213
|
+
const pending = await (async () => {
|
|
214
|
+
try {
|
|
215
|
+
const [, fdList] = await tConn.migrate.list();
|
|
216
|
+
return fdList.map((fd: { file: string }) =>
|
|
217
|
+
fd.file.replace(".js", "")
|
|
218
|
+
);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
})();
|
|
223
|
+
const currentVersion = await (async () => {
|
|
224
|
+
try {
|
|
225
|
+
return tConn.migrate.currentVersion();
|
|
226
|
+
} catch (err) {
|
|
227
|
+
return "error";
|
|
228
|
+
}
|
|
229
|
+
})();
|
|
230
|
+
|
|
231
|
+
const connection =
|
|
232
|
+
knexOptions.connection as Knex.MySql2ConnectionConfig;
|
|
233
|
+
|
|
234
|
+
await tConn.destroy();
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
name: connKey.replace("_master", ""),
|
|
238
|
+
connKey,
|
|
239
|
+
connString: `${knexOptions.client}://${connection.user ?? ""}@${
|
|
240
|
+
connection.host
|
|
241
|
+
}:${connection.port ?? 3306}/${connection.database}` as ConnString,
|
|
242
|
+
currentVersion,
|
|
243
|
+
status,
|
|
244
|
+
pending,
|
|
245
|
+
};
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
const preparedCodes: GenMigrationCode[] = await (async () => {
|
|
250
|
+
const status0conn = statuses.find((status) => status.status === 0);
|
|
251
|
+
if (status0conn === undefined) {
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const compareDBconn = knex(Sonamu.dbConfig[status0conn.connKey]);
|
|
256
|
+
const genCodes = await this.compareMigrations(compareDBconn);
|
|
257
|
+
|
|
258
|
+
await compareDBconn.destroy();
|
|
259
|
+
|
|
260
|
+
return genCodes;
|
|
261
|
+
})();
|
|
262
|
+
|
|
263
|
+
return {
|
|
264
|
+
conns: statuses,
|
|
265
|
+
codes: normal,
|
|
266
|
+
preparedCodes,
|
|
267
|
+
};
|
|
268
|
+
/*
|
|
269
|
+
TS/JS 코드 컴파일 상태 확인
|
|
270
|
+
1. 원본 파일 없는 JS파일이 존재하는 경우: 삭제
|
|
271
|
+
2. 컴파일 되지 않은 TS파일이 존재하는 경우: throw 쳐서 데브 서버 오픈 요청
|
|
272
|
+
|
|
273
|
+
DB 마이그레이션 상태 확인
|
|
274
|
+
1. 전체 DB설정에 대해서 현재 마이그레이션 상태 확인
|
|
275
|
+
- connKey: string
|
|
276
|
+
- status: number
|
|
277
|
+
- currentVersion: string
|
|
278
|
+
- list: { file: string; directory: string }[]
|
|
279
|
+
|
|
280
|
+
*/
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async runAction(
|
|
284
|
+
action: "latest" | "rollback",
|
|
285
|
+
targets: string[]
|
|
286
|
+
): Promise<
|
|
287
|
+
{
|
|
288
|
+
connKey: string;
|
|
289
|
+
batchNo: number;
|
|
290
|
+
applied: string[];
|
|
291
|
+
}[]
|
|
292
|
+
> {
|
|
293
|
+
// get connections
|
|
294
|
+
const conns = (
|
|
295
|
+
await Promise.all(
|
|
296
|
+
targets.map(async (target) => {
|
|
297
|
+
const knexOptions =
|
|
298
|
+
Sonamu.dbConfig[target as keyof typeof Sonamu.dbConfig];
|
|
299
|
+
if (knexOptions === undefined) {
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
connKey: target,
|
|
305
|
+
knex: knex(knexOptions),
|
|
306
|
+
};
|
|
307
|
+
})
|
|
308
|
+
)
|
|
309
|
+
).filter(nonNullable);
|
|
310
|
+
|
|
311
|
+
// action
|
|
312
|
+
const result = await (async () => {
|
|
313
|
+
switch (action) {
|
|
314
|
+
case "latest":
|
|
315
|
+
return Promise.all(
|
|
316
|
+
conns.map(async ({ connKey, knex }) => {
|
|
317
|
+
const [batchNo, applied] = await knex.migrate.latest();
|
|
318
|
+
return {
|
|
319
|
+
connKey,
|
|
320
|
+
batchNo,
|
|
321
|
+
applied,
|
|
322
|
+
};
|
|
323
|
+
})
|
|
324
|
+
);
|
|
325
|
+
case "rollback":
|
|
326
|
+
return Promise.all(
|
|
327
|
+
conns.map(async ({ connKey, knex }) => {
|
|
328
|
+
const [batchNo, applied] = await knex.migrate.rollback();
|
|
329
|
+
return {
|
|
330
|
+
connKey,
|
|
331
|
+
batchNo,
|
|
332
|
+
applied,
|
|
333
|
+
};
|
|
334
|
+
})
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
})();
|
|
338
|
+
|
|
339
|
+
// destroy
|
|
340
|
+
await Promise.all(
|
|
341
|
+
conns.map(({ knex }) => {
|
|
342
|
+
return knex.destroy();
|
|
343
|
+
})
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
async delCodes(codeNames: string[]): Promise<number> {
|
|
350
|
+
const { conns } = await this.getStatus();
|
|
351
|
+
if (
|
|
352
|
+
conns.some((conn) => {
|
|
353
|
+
return codeNames.some(
|
|
354
|
+
(codeName) => conn.pending.includes(codeName) === false
|
|
355
|
+
);
|
|
356
|
+
})
|
|
357
|
+
) {
|
|
358
|
+
throw new Error(
|
|
359
|
+
"You cannot delete a migration file if there is already applied."
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const delFiles = codeNames
|
|
364
|
+
.map((codeName) => [
|
|
365
|
+
`${Sonamu.apiRootPath}/src/migrations/${codeName}.ts`,
|
|
366
|
+
`${Sonamu.apiRootPath}/dist/migrations/${codeName}.js`,
|
|
367
|
+
])
|
|
368
|
+
.flat();
|
|
369
|
+
|
|
370
|
+
const res = await Promise.all(
|
|
371
|
+
delFiles.map((delFile) => {
|
|
372
|
+
if (existsSync(delFile)) {
|
|
373
|
+
console.log(chalk.red(`DELETE: ${delFile}`));
|
|
374
|
+
unlinkSync(delFile);
|
|
375
|
+
return delFiles.includes(".ts") ? 1 : 0;
|
|
376
|
+
}
|
|
377
|
+
return 0;
|
|
378
|
+
})
|
|
379
|
+
);
|
|
380
|
+
return sum(res);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async generatePreparedCodes(): Promise<number> {
|
|
384
|
+
const { preparedCodes } = await this.getStatus();
|
|
385
|
+
if (preparedCodes.length === 0) {
|
|
386
|
+
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
387
|
+
return 0;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// 실제 코드 생성
|
|
391
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
392
|
+
preparedCodes
|
|
393
|
+
.filter((pcode) => pcode.formatted)
|
|
394
|
+
.map((pcode, index) => {
|
|
395
|
+
const dateTag = DateTime.local()
|
|
396
|
+
.plus({ seconds: index })
|
|
397
|
+
.toFormat("yyyyMMddHHmmss");
|
|
398
|
+
const filePath = `${migrationsDir}/${dateTag}_${pcode.title}.ts`;
|
|
399
|
+
writeFileSync(filePath, pcode.formatted!);
|
|
400
|
+
console.log(chalk.green(`MIGRTAION CRETATED ${filePath}`));
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
return preparedCodes.length;
|
|
404
|
+
}
|
|
405
|
+
|
|
111
406
|
async clearPendingList(): Promise<void> {
|
|
112
407
|
const [, pendingList] = (await this.targets.pending.migrate.list()) as [
|
|
113
408
|
unknown,
|
|
@@ -129,7 +424,7 @@ export class Migrator {
|
|
|
129
424
|
}
|
|
130
425
|
|
|
131
426
|
async check(): Promise<void> {
|
|
132
|
-
const codes = await this.compareMigrations();
|
|
427
|
+
const codes = await this.compareMigrations(this.targets.compare!);
|
|
133
428
|
if (codes.length === 0) {
|
|
134
429
|
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
135
430
|
return;
|
|
@@ -161,27 +456,24 @@ export class Migrator {
|
|
|
161
456
|
}
|
|
162
457
|
|
|
163
458
|
console.time(chalk.blue("Migrator - runShadowTest"));
|
|
164
|
-
|
|
459
|
+
await this.runShadowTest();
|
|
165
460
|
console.timeEnd(chalk.blue("Migrator - runShadowTest"));
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
return;
|
|
461
|
+
await Promise.all(
|
|
462
|
+
this.targets.apply.map(async (applyDb) => {
|
|
463
|
+
const label = chalk.green(
|
|
464
|
+
`APPLIED ${
|
|
465
|
+
applyDb.client.connectionSettings.host
|
|
466
|
+
} ${applyDb.client.database()}`
|
|
467
|
+
);
|
|
468
|
+
console.time(label);
|
|
469
|
+
const [,] = await applyDb.migrate.latest();
|
|
470
|
+
console.timeEnd(label);
|
|
471
|
+
})
|
|
472
|
+
);
|
|
181
473
|
}
|
|
182
474
|
|
|
183
475
|
// MD-DB간 비교하여 코드 생성 리턴
|
|
184
|
-
const codes = await this.compareMigrations();
|
|
476
|
+
const codes = await this.compareMigrations(this.targets.compare!);
|
|
185
477
|
if (codes.length === 0) {
|
|
186
478
|
console.log(chalk.green("\n현재 모두 싱크된 상태입니다."));
|
|
187
479
|
return;
|
|
@@ -299,7 +591,13 @@ export class Migrator {
|
|
|
299
591
|
}
|
|
300
592
|
}
|
|
301
593
|
|
|
302
|
-
async runShadowTest(): Promise<
|
|
594
|
+
async runShadowTest(): Promise<
|
|
595
|
+
{
|
|
596
|
+
connKey: string;
|
|
597
|
+
batchNo: number;
|
|
598
|
+
applied: string[];
|
|
599
|
+
}[]
|
|
600
|
+
> {
|
|
303
601
|
// ShadowDB 생성 후 테스트 진행
|
|
304
602
|
const tdb = knex(Sonamu.dbConfig.test);
|
|
305
603
|
const tdbConn = Sonamu.dbConfig.test.connection as Knex.ConnectionConfig;
|
|
@@ -337,24 +635,31 @@ export class Migrator {
|
|
|
337
635
|
connection: {
|
|
338
636
|
...tdbConn,
|
|
339
637
|
database: shadowDatabase,
|
|
638
|
+
password: tdbConn.password,
|
|
340
639
|
},
|
|
341
640
|
});
|
|
342
641
|
|
|
343
642
|
try {
|
|
344
|
-
const [batchNo,
|
|
643
|
+
const [batchNo, applied] = await sdb.migrate.latest();
|
|
345
644
|
console.log(chalk.green("Shadow DB 테스트에 성공했습니다!"), {
|
|
346
645
|
batchNo,
|
|
347
|
-
|
|
646
|
+
applied,
|
|
348
647
|
});
|
|
349
648
|
|
|
350
649
|
// 생성한 Shadow DB 삭제
|
|
351
650
|
console.log(chalk.magenta(`${shadowDatabase} 삭제`));
|
|
352
651
|
await sdb.raw(`DROP DATABASE IF EXISTS ${shadowDatabase};`);
|
|
353
652
|
|
|
354
|
-
return
|
|
653
|
+
return [
|
|
654
|
+
{
|
|
655
|
+
connKey: "shadow",
|
|
656
|
+
batchNo,
|
|
657
|
+
applied,
|
|
658
|
+
},
|
|
659
|
+
];
|
|
355
660
|
} catch (e) {
|
|
356
|
-
console.error(
|
|
357
|
-
|
|
661
|
+
console.error(e);
|
|
662
|
+
throw new ServiceUnavailableException("Shadow DB 테스트 진행 중 에러");
|
|
358
663
|
} finally {
|
|
359
664
|
await sdb.destroy();
|
|
360
665
|
}
|
|
@@ -388,45 +693,54 @@ export class Migrator {
|
|
|
388
693
|
console.timeEnd(chalk.red("delete migration files"));
|
|
389
694
|
}
|
|
390
695
|
|
|
391
|
-
async compareMigrations(): Promise<GenMigrationCode[]> {
|
|
696
|
+
async compareMigrations(compareDB: Knex): Promise<GenMigrationCode[]> {
|
|
392
697
|
// MD 순회하여 싱크
|
|
393
|
-
const
|
|
698
|
+
const entityIds = EntityManager.getAllIds();
|
|
394
699
|
|
|
395
700
|
// 조인테이블 포함하여 MD에서 MigrationSet 추출
|
|
396
|
-
const
|
|
397
|
-
.filter((
|
|
398
|
-
const
|
|
399
|
-
return
|
|
701
|
+
const entitySetsWithJoinTable = entityIds
|
|
702
|
+
.filter((entityId) => {
|
|
703
|
+
const entity = EntityManager.get(entityId);
|
|
704
|
+
return entity.props.length > 0;
|
|
400
705
|
})
|
|
401
|
-
.map((
|
|
402
|
-
const
|
|
403
|
-
return this.getMigrationSetFromMD(
|
|
706
|
+
.map((entityId) => {
|
|
707
|
+
const entity = EntityManager.get(entityId);
|
|
708
|
+
return this.getMigrationSetFromMD(entity);
|
|
404
709
|
});
|
|
405
710
|
|
|
406
711
|
// 조인테이블만 추출
|
|
407
712
|
const joinTables = uniqBy(
|
|
408
|
-
|
|
713
|
+
entitySetsWithJoinTable.map((entitySet) => entitySet.joinTables).flat(),
|
|
409
714
|
(joinTable) => {
|
|
410
715
|
return joinTable.table;
|
|
411
716
|
}
|
|
412
717
|
);
|
|
413
718
|
|
|
414
719
|
// 조인테이블 포함하여 MigrationSet 배열
|
|
415
|
-
const
|
|
720
|
+
const entitySets: MigrationSet[] = [
|
|
721
|
+
...entitySetsWithJoinTable,
|
|
722
|
+
...joinTables,
|
|
723
|
+
];
|
|
416
724
|
|
|
417
725
|
let codes: GenMigrationCode[] = (
|
|
418
726
|
await Promise.all(
|
|
419
|
-
|
|
420
|
-
const dbSet = await this.getMigrationSetFromDB(
|
|
727
|
+
entitySets.map(async (entitySet) => {
|
|
728
|
+
const dbSet = await this.getMigrationSetFromDB(
|
|
729
|
+
compareDB,
|
|
730
|
+
entitySet.table
|
|
731
|
+
);
|
|
421
732
|
if (dbSet === null) {
|
|
422
733
|
// 기존 테이블 없음, 새로 테이블 생성
|
|
423
734
|
return [
|
|
424
735
|
this.generateCreateCode_ColumnAndIndexes(
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
736
|
+
entitySet.table,
|
|
737
|
+
entitySet.columns,
|
|
738
|
+
entitySet.indexes
|
|
739
|
+
),
|
|
740
|
+
...this.generateCreateCode_Foreign(
|
|
741
|
+
entitySet.table,
|
|
742
|
+
entitySet.foreigns
|
|
428
743
|
),
|
|
429
|
-
...this.generateCreateCode_Foreign(smdSet.table, smdSet.foreigns),
|
|
430
744
|
];
|
|
431
745
|
}
|
|
432
746
|
|
|
@@ -436,20 +750,20 @@ export class Migrator {
|
|
|
436
750
|
).map((key) => {
|
|
437
751
|
// 배열 원소의 순서가 달라서 불일치가 발생하는걸 방지하기 위해 각 항목별로 정렬 처리 후 비교
|
|
438
752
|
if (key === "columnsAndIndexes") {
|
|
439
|
-
const
|
|
753
|
+
const entityColumns = sortBy(entitySet.columns, (a) => a.name);
|
|
440
754
|
const dbColumns = sortBy(dbSet.columns, (a) => a.name);
|
|
441
755
|
|
|
442
756
|
/* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인
|
|
443
|
-
const
|
|
757
|
+
const entityCreatedAt = entitySet.columns.find(
|
|
444
758
|
(col) => col.name === "created_at"
|
|
445
759
|
);
|
|
446
760
|
const dbCreatedAt = dbSet.columns.find(
|
|
447
761
|
(col) => col.name === "created_at"
|
|
448
762
|
);
|
|
449
|
-
console.debug({
|
|
763
|
+
console.debug({ entityCreatedAt, dbCreatedAt });
|
|
450
764
|
*/
|
|
451
765
|
|
|
452
|
-
const
|
|
766
|
+
const entityIndexes = sortBy(entitySet.indexes, (a) =>
|
|
453
767
|
[
|
|
454
768
|
a.type,
|
|
455
769
|
...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1)),
|
|
@@ -462,17 +776,17 @@ export class Migrator {
|
|
|
462
776
|
].join("-")
|
|
463
777
|
);
|
|
464
778
|
|
|
465
|
-
const isEqualColumns = equal(
|
|
466
|
-
const isEqualIndexes = equal(
|
|
779
|
+
const isEqualColumns = equal(entityColumns, dbColumns);
|
|
780
|
+
const isEqualIndexes = equal(entityIndexes, dbIndexes);
|
|
467
781
|
if (isEqualColumns && isEqualIndexes) {
|
|
468
782
|
return null;
|
|
469
783
|
} else {
|
|
470
|
-
// this.showMigrationSet("MD",
|
|
784
|
+
// this.showMigrationSet("MD", entitySet);
|
|
471
785
|
// this.showMigrationSet("DB", dbSet);
|
|
472
786
|
return this.generateAlterCode_ColumnAndIndexes(
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
787
|
+
entitySet.table,
|
|
788
|
+
entityColumns,
|
|
789
|
+
entityIndexes,
|
|
476
790
|
dbColumns,
|
|
477
791
|
dbIndexes
|
|
478
792
|
);
|
|
@@ -488,18 +802,18 @@ export class Migrator {
|
|
|
488
802
|
};
|
|
489
803
|
};
|
|
490
804
|
|
|
491
|
-
const
|
|
805
|
+
const entityForeigns = sortBy(entitySet.foreigns, (a) =>
|
|
492
806
|
[a.to, ...a.columns].join("-")
|
|
493
807
|
).map((f) => replaceNoActionOnMySQL(f));
|
|
494
808
|
const dbForeigns = sortBy(dbSet.foreigns, (a) =>
|
|
495
809
|
[a.to, ...a.columns].join("-")
|
|
496
810
|
).map((f) => replaceNoActionOnMySQL(f));
|
|
497
811
|
|
|
498
|
-
if (equal(
|
|
499
|
-
console.dir({
|
|
812
|
+
if (equal(entityForeigns, dbForeigns) === false) {
|
|
813
|
+
console.dir({ entityForeigns, dbForeigns }, { depth: null });
|
|
500
814
|
return this.generateAlterCode_Foreigns(
|
|
501
|
-
|
|
502
|
-
|
|
815
|
+
entitySet.table,
|
|
816
|
+
entityForeigns,
|
|
503
817
|
dbForeigns
|
|
504
818
|
);
|
|
505
819
|
}
|
|
@@ -536,10 +850,16 @@ export class Migrator {
|
|
|
536
850
|
/*
|
|
537
851
|
기존 테이블 정보 읽어서 MigrationSet 형식으로 리턴
|
|
538
852
|
*/
|
|
539
|
-
async getMigrationSetFromDB(
|
|
853
|
+
async getMigrationSetFromDB(
|
|
854
|
+
compareDB: Knex,
|
|
855
|
+
table: string
|
|
856
|
+
): Promise<MigrationSet | null> {
|
|
540
857
|
let dbColumns: DBColumn[], dbIndexes: DBIndex[], dbForeigns: DBForeign[];
|
|
541
858
|
try {
|
|
542
|
-
[dbColumns, dbIndexes, dbForeigns] = await this.readTable(
|
|
859
|
+
[dbColumns, dbIndexes, dbForeigns] = await this.readTable(
|
|
860
|
+
compareDB,
|
|
861
|
+
table
|
|
862
|
+
);
|
|
543
863
|
} catch (e: unknown) {
|
|
544
864
|
if (isKnexError(e) && e.code === "ER_NO_SUCH_TABLE") {
|
|
545
865
|
return null;
|
|
@@ -695,19 +1015,14 @@ export class Migrator {
|
|
|
695
1015
|
기존 테이블 읽어서 cols, indexes 반환
|
|
696
1016
|
*/
|
|
697
1017
|
async readTable(
|
|
1018
|
+
compareDB: Knex,
|
|
698
1019
|
tableName: string
|
|
699
1020
|
): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {
|
|
700
1021
|
// 테이블 정보
|
|
701
1022
|
try {
|
|
702
|
-
const [cols] = await
|
|
703
|
-
|
|
704
|
-
);
|
|
705
|
-
const [indexes] = await this.targets.compare!.raw(
|
|
706
|
-
`SHOW INDEX FROM ${tableName}`
|
|
707
|
-
);
|
|
708
|
-
const [[row]] = await this.targets.compare!.raw(
|
|
709
|
-
`SHOW CREATE TABLE ${tableName}`
|
|
710
|
-
);
|
|
1023
|
+
const [cols] = await compareDB.raw(`SHOW FIELDS FROM ${tableName}`);
|
|
1024
|
+
const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);
|
|
1025
|
+
const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);
|
|
711
1026
|
const ddl = row["Create Table"];
|
|
712
1027
|
const matched = ddl.match(/CONSTRAINT .+/g);
|
|
713
1028
|
const foreignKeys = (matched ?? []).map((line: string) => {
|
|
@@ -766,8 +1081,8 @@ export class Migrator {
|
|
|
766
1081
|
/*
|
|
767
1082
|
MD 내용 읽어서 MigrationSetAndJoinTable 추출
|
|
768
1083
|
*/
|
|
769
|
-
getMigrationSetFromMD(
|
|
770
|
-
const migrationSet: MigrationSetAndJoinTable =
|
|
1084
|
+
getMigrationSetFromMD(entity: Entity): MigrationSetAndJoinTable {
|
|
1085
|
+
const migrationSet: MigrationSetAndJoinTable = entity.props.reduce(
|
|
771
1086
|
(r, prop) => {
|
|
772
1087
|
// virtual 필드 제외
|
|
773
1088
|
if (isVirtualProp(prop)) {
|
|
@@ -818,10 +1133,10 @@ export class Migrator {
|
|
|
818
1133
|
|
|
819
1134
|
if (isManyToManyRelationProp(prop)) {
|
|
820
1135
|
// ManyToMany 케이스
|
|
821
|
-
const relMd =
|
|
1136
|
+
const relMd = EntityManager.get(prop.with);
|
|
822
1137
|
const [table1, table2] = prop.joinTable.split("__");
|
|
823
1138
|
const join = {
|
|
824
|
-
from: `${
|
|
1139
|
+
from: `${entity.table}.id`,
|
|
825
1140
|
through: {
|
|
826
1141
|
from: `${prop.joinTable}.${singularize(table1)}_id`,
|
|
827
1142
|
to: `${prop.joinTable}.${singularize(table2)}_id`,
|
|
@@ -840,7 +1155,7 @@ export class Migrator {
|
|
|
840
1155
|
columns: ["uuid"],
|
|
841
1156
|
},
|
|
842
1157
|
// 조인 테이블에 걸린 인덱스 찾아와서 연결
|
|
843
|
-
...
|
|
1158
|
+
...entity.indexes
|
|
844
1159
|
.filter((index) =>
|
|
845
1160
|
index.columns.find((col) =>
|
|
846
1161
|
col.includes(prop.joinTable + ".")
|
|
@@ -907,7 +1222,7 @@ export class Migrator {
|
|
|
907
1222
|
return r;
|
|
908
1223
|
},
|
|
909
1224
|
{
|
|
910
|
-
table:
|
|
1225
|
+
table: entity.table,
|
|
911
1226
|
columns: [] as MigrationColumn[],
|
|
912
1227
|
indexes: [] as MigrationIndex[],
|
|
913
1228
|
foreigns: [] as MigrationForeign[],
|
|
@@ -916,7 +1231,7 @@ export class Migrator {
|
|
|
916
1231
|
);
|
|
917
1232
|
|
|
918
1233
|
// indexes
|
|
919
|
-
migrationSet.indexes =
|
|
1234
|
+
migrationSet.indexes = entity.indexes.filter((index) =>
|
|
920
1235
|
index.columns.find((col) => col.includes(".") === false)
|
|
921
1236
|
);
|
|
922
1237
|
|
|
@@ -1183,8 +1498,8 @@ export class Migrator {
|
|
|
1183
1498
|
|
|
1184
1499
|
generateAlterCode_ColumnAndIndexes(
|
|
1185
1500
|
table: string,
|
|
1186
|
-
|
|
1187
|
-
|
|
1501
|
+
entityColumns: MigrationColumn[],
|
|
1502
|
+
entityIndexes: MigrationIndex[],
|
|
1188
1503
|
dbColumns: MigrationColumn[],
|
|
1189
1504
|
dbIndexes: MigrationIndex[]
|
|
1190
1505
|
): GenMigrationCode[] {
|
|
@@ -1201,16 +1516,16 @@ export class Migrator {
|
|
|
1201
1516
|
*/
|
|
1202
1517
|
|
|
1203
1518
|
// 각 컬럼 이름 기준으로 add, drop, alter 여부 확인
|
|
1204
|
-
const alterColumnsTo = this.getAlterColumnsTo(
|
|
1519
|
+
const alterColumnsTo = this.getAlterColumnsTo(entityColumns, dbColumns);
|
|
1205
1520
|
|
|
1206
1521
|
// 추출된 컬럼들을 기준으로 각각 라인 생성
|
|
1207
1522
|
const alterColumnLinesTo = this.getAlterColumnLinesTo(
|
|
1208
1523
|
alterColumnsTo,
|
|
1209
|
-
|
|
1524
|
+
entityColumns
|
|
1210
1525
|
);
|
|
1211
1526
|
|
|
1212
1527
|
// 인덱스의 add, drop 여부 확인
|
|
1213
|
-
const alterIndexesTo = this.getAlterIndexesTo(
|
|
1528
|
+
const alterIndexesTo = this.getAlterIndexesTo(entityIndexes, dbIndexes);
|
|
1214
1529
|
|
|
1215
1530
|
// 추출된 인덱스들을 기준으로 각각 라인 생성
|
|
1216
1531
|
const alterIndexLinesTo = this.getAlterIndexLinesTo(
|
|
@@ -1275,7 +1590,7 @@ export class Migrator {
|
|
|
1275
1590
|
}
|
|
1276
1591
|
|
|
1277
1592
|
getAlterColumnsTo(
|
|
1278
|
-
|
|
1593
|
+
entityColumns: MigrationColumn[],
|
|
1279
1594
|
dbColumns: MigrationColumn[]
|
|
1280
1595
|
) {
|
|
1281
1596
|
const columnsTo = {
|
|
@@ -1286,11 +1601,11 @@ export class Migrator {
|
|
|
1286
1601
|
|
|
1287
1602
|
// 컬럼명 기준 비교
|
|
1288
1603
|
const extraColumns = {
|
|
1289
|
-
db: differenceBy(dbColumns,
|
|
1290
|
-
|
|
1604
|
+
db: differenceBy(dbColumns, entityColumns, (col) => col.name),
|
|
1605
|
+
entity: differenceBy(entityColumns, dbColumns, (col) => col.name),
|
|
1291
1606
|
};
|
|
1292
|
-
if (extraColumns.
|
|
1293
|
-
columnsTo.add = columnsTo.add.concat(extraColumns.
|
|
1607
|
+
if (extraColumns.entity.length > 0) {
|
|
1608
|
+
columnsTo.add = columnsTo.add.concat(extraColumns.entity);
|
|
1294
1609
|
}
|
|
1295
1610
|
if (extraColumns.db.length > 0) {
|
|
1296
1611
|
columnsTo.drop = columnsTo.drop.concat(extraColumns.db);
|
|
@@ -1299,11 +1614,11 @@ export class Migrator {
|
|
|
1299
1614
|
// 동일 컬럼명의 세부 필드 비교
|
|
1300
1615
|
const sameDbColumns = intersectionBy(
|
|
1301
1616
|
dbColumns,
|
|
1302
|
-
|
|
1617
|
+
entityColumns,
|
|
1303
1618
|
(col) => col.name
|
|
1304
1619
|
);
|
|
1305
1620
|
const sameMdColumns = intersectionBy(
|
|
1306
|
-
|
|
1621
|
+
entityColumns,
|
|
1307
1622
|
dbColumns,
|
|
1308
1623
|
(col) => col.name
|
|
1309
1624
|
);
|
|
@@ -1316,7 +1631,7 @@ export class Migrator {
|
|
|
1316
1631
|
|
|
1317
1632
|
getAlterColumnLinesTo(
|
|
1318
1633
|
columnsTo: ReturnType<Migrator["getAlterColumnsTo"]>,
|
|
1319
|
-
|
|
1634
|
+
entityColumns: MigrationColumn[]
|
|
1320
1635
|
) {
|
|
1321
1636
|
let linesTo = {
|
|
1322
1637
|
add: {
|
|
@@ -1356,19 +1671,21 @@ export class Migrator {
|
|
|
1356
1671
|
};
|
|
1357
1672
|
linesTo.alter = columnsTo.alter.reduce(
|
|
1358
1673
|
(r, dbColumn) => {
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1674
|
+
const entityColumn = entityColumns.find(
|
|
1675
|
+
(col) => col.name == dbColumn.name
|
|
1676
|
+
);
|
|
1677
|
+
if (entityColumn === undefined) {
|
|
1361
1678
|
return r;
|
|
1362
1679
|
}
|
|
1363
1680
|
|
|
1364
1681
|
// 컬럼 변경사항
|
|
1365
1682
|
const columnDiffUp = difference(
|
|
1366
|
-
this.genColumnDefinitions([
|
|
1683
|
+
this.genColumnDefinitions([entityColumn]),
|
|
1367
1684
|
this.genColumnDefinitions([dbColumn])
|
|
1368
1685
|
);
|
|
1369
1686
|
const columnDiffDown = difference(
|
|
1370
1687
|
this.genColumnDefinitions([dbColumn]),
|
|
1371
|
-
this.genColumnDefinitions([
|
|
1688
|
+
this.genColumnDefinitions([entityColumn])
|
|
1372
1689
|
);
|
|
1373
1690
|
if (columnDiffUp.length > 0) {
|
|
1374
1691
|
r.up = [
|
|
@@ -1394,22 +1711,25 @@ export class Migrator {
|
|
|
1394
1711
|
return linesTo;
|
|
1395
1712
|
}
|
|
1396
1713
|
|
|
1397
|
-
getAlterIndexesTo(
|
|
1714
|
+
getAlterIndexesTo(
|
|
1715
|
+
entityIndexes: MigrationIndex[],
|
|
1716
|
+
dbIndexes: MigrationIndex[]
|
|
1717
|
+
) {
|
|
1398
1718
|
// 인덱스 비교
|
|
1399
1719
|
let indexesTo = {
|
|
1400
1720
|
add: [] as MigrationIndex[],
|
|
1401
1721
|
drop: [] as MigrationIndex[],
|
|
1402
1722
|
};
|
|
1403
1723
|
const extraIndexes = {
|
|
1404
|
-
db: differenceBy(dbIndexes,
|
|
1724
|
+
db: differenceBy(dbIndexes, entityIndexes, (col) =>
|
|
1405
1725
|
[col.type, col.columns.join("-")].join("//")
|
|
1406
1726
|
),
|
|
1407
|
-
|
|
1727
|
+
entity: differenceBy(entityIndexes, dbIndexes, (col) =>
|
|
1408
1728
|
[col.type, col.columns.join("-")].join("//")
|
|
1409
1729
|
),
|
|
1410
1730
|
};
|
|
1411
|
-
if (extraIndexes.
|
|
1412
|
-
indexesTo.add = indexesTo.add.concat(extraIndexes.
|
|
1731
|
+
if (extraIndexes.entity.length > 0) {
|
|
1732
|
+
indexesTo.add = indexesTo.add.concat(extraIndexes.entity);
|
|
1413
1733
|
}
|
|
1414
1734
|
if (extraIndexes.db.length > 0) {
|
|
1415
1735
|
indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);
|
|
@@ -1481,27 +1801,27 @@ export class Migrator {
|
|
|
1481
1801
|
|
|
1482
1802
|
generateAlterCode_Foreigns(
|
|
1483
1803
|
table: string,
|
|
1484
|
-
|
|
1804
|
+
entityForeigns: MigrationForeign[],
|
|
1485
1805
|
dbForeigns: MigrationForeign[]
|
|
1486
1806
|
): GenMigrationCode[] {
|
|
1487
|
-
// console.log({
|
|
1807
|
+
// console.log({ entityForeigns, dbForeigns });
|
|
1488
1808
|
|
|
1489
1809
|
const getKey = (mf: MigrationForeign): string => {
|
|
1490
1810
|
return [mf.columns.join("-"), mf.to].join("///");
|
|
1491
1811
|
};
|
|
1492
|
-
const fkTo =
|
|
1493
|
-
(result,
|
|
1812
|
+
const fkTo = entityForeigns.reduce(
|
|
1813
|
+
(result, entityF) => {
|
|
1494
1814
|
const matchingDbF = dbForeigns.find(
|
|
1495
|
-
(dbF) => getKey(
|
|
1815
|
+
(dbF) => getKey(entityF) === getKey(dbF)
|
|
1496
1816
|
);
|
|
1497
1817
|
if (!matchingDbF) {
|
|
1498
|
-
result.add.push(
|
|
1818
|
+
result.add.push(entityF);
|
|
1499
1819
|
return result;
|
|
1500
1820
|
}
|
|
1501
1821
|
|
|
1502
|
-
if (equal(
|
|
1822
|
+
if (equal(entityF, matchingDbF) === false) {
|
|
1503
1823
|
result.alterSrc.push(matchingDbF);
|
|
1504
|
-
result.alterDst.push(
|
|
1824
|
+
result.alterDst.push(entityF);
|
|
1505
1825
|
return result;
|
|
1506
1826
|
}
|
|
1507
1827
|
return result;
|