sonamu 0.1.0 → 0.1.4
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/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +1 -0
- package/dist/entity/entity-manager.js.map +1 -1
- package/dist/entity/entity-utils.d.ts.map +1 -1
- package/dist/entity/entity-utils.js +1 -1
- package/dist/entity/entity-utils.js.map +1 -1
- package/dist/entity/entity.d.ts +9 -0
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +147 -3
- package/dist/entity/entity.js.map +1 -1
- package/dist/entity/migrator.d.ts.map +1 -1
- package/dist/entity/migrator.js +43 -12
- package/dist/entity/migrator.js.map +1 -1
- package/dist/syncer/syncer.d.ts +6 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +62 -41
- package/dist/syncer/syncer.js.map +1 -1
- package/dist/templates/entity.template.d.ts +1 -1
- package/dist/templates/entity.template.d.ts.map +1 -1
- package/dist/templates/entity.template.js +43 -13
- package/dist/templates/entity.template.js.map +1 -1
- package/dist/templates/generated.template.d.ts.map +1 -1
- package/dist/templates/generated.template.js +18 -0
- package/dist/templates/generated.template.js.map +1 -1
- package/dist/templates/view_form.template.d.ts +1 -1
- package/dist/templates/view_list.template.d.ts +1 -1
- package/dist/types/types.d.ts +5 -5
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js.map +1 -1
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +4 -1
- package/dist/utils/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/entity/entity-manager.ts +1 -0
- package/src/entity/entity-utils.ts +2 -0
- package/src/entity/entity.ts +180 -3
- package/src/entity/migrator.ts +54 -13
- package/src/syncer/syncer.ts +84 -44
- package/src/templates/entity.template.ts +42 -9
- package/src/templates/generated.template.ts +27 -2
- package/src/types/types.ts +4 -3
- package/src/utils/utils.ts +5 -1
package/src/entity/migrator.ts
CHANGED
|
@@ -137,6 +137,17 @@ export class Migrator {
|
|
|
137
137
|
}> {
|
|
138
138
|
const srcMigrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
139
139
|
const distMigrationsDir = `${Sonamu.apiRootPath}/dist/migrations`;
|
|
140
|
+
|
|
141
|
+
if (existsSync(srcMigrationsDir) === false) {
|
|
142
|
+
mkdirSync(srcMigrationsDir, {
|
|
143
|
+
recursive: true,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (existsSync(distMigrationsDir) === false) {
|
|
147
|
+
mkdirSync(distMigrationsDir, {
|
|
148
|
+
recursive: true,
|
|
149
|
+
});
|
|
150
|
+
}
|
|
140
151
|
const srcMigrations = readdirSync(srcMigrationsDir)
|
|
141
152
|
.filter((f) => f.endsWith(".ts"))
|
|
142
153
|
.map((f) => f.split(".")[0]);
|
|
@@ -203,9 +214,10 @@ export class Migrator {
|
|
|
203
214
|
connKeys.map(async (connKey) => {
|
|
204
215
|
const knexOptions = Sonamu.dbConfig[connKey];
|
|
205
216
|
const tConn = knex(knexOptions);
|
|
217
|
+
|
|
206
218
|
const status = await (async () => {
|
|
207
219
|
try {
|
|
208
|
-
return tConn.migrate.status();
|
|
220
|
+
return await tConn.migrate.status();
|
|
209
221
|
} catch (err) {
|
|
210
222
|
return "error";
|
|
211
223
|
}
|
|
@@ -874,12 +886,14 @@ export class Migrator {
|
|
|
874
886
|
name: dbColumn.Field,
|
|
875
887
|
nullable: dbColumn.Null !== "NO",
|
|
876
888
|
...dbColType,
|
|
877
|
-
...
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
889
|
+
...(() => {
|
|
890
|
+
if (dbColumn.Default !== null) {
|
|
891
|
+
return {
|
|
892
|
+
defaultTo: dbColumn.Default,
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
return {};
|
|
896
|
+
})(),
|
|
883
897
|
};
|
|
884
898
|
});
|
|
885
899
|
|
|
@@ -1020,7 +1034,23 @@ export class Migrator {
|
|
|
1020
1034
|
): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {
|
|
1021
1035
|
// 테이블 정보
|
|
1022
1036
|
try {
|
|
1023
|
-
const [
|
|
1037
|
+
const [_cols] = (await compareDB.raw(
|
|
1038
|
+
`SHOW FIELDS FROM ${tableName}`
|
|
1039
|
+
)) as [DBColumn[]];
|
|
1040
|
+
const cols = _cols.map((col) => ({
|
|
1041
|
+
...col,
|
|
1042
|
+
// Default 값은 숫자나 MySQL Expression이 아닌 경우 ""로 감싸줌
|
|
1043
|
+
...(col.Default !== null
|
|
1044
|
+
? {
|
|
1045
|
+
Default:
|
|
1046
|
+
col.Default.replace(/[0-9]+/g, "").length > 0 &&
|
|
1047
|
+
col.Extra !== "DEFAULT_GENERATED"
|
|
1048
|
+
? `"${col.Default}"`
|
|
1049
|
+
: col.Default,
|
|
1050
|
+
}
|
|
1051
|
+
: {}),
|
|
1052
|
+
}));
|
|
1053
|
+
|
|
1024
1054
|
const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);
|
|
1025
1055
|
const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);
|
|
1026
1056
|
const ddl = row["Create Table"];
|
|
@@ -1115,10 +1145,14 @@ export class Migrator {
|
|
|
1115
1145
|
? { length: prop.length }
|
|
1116
1146
|
: {}),
|
|
1117
1147
|
nullable: prop.nullable === true,
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1148
|
+
...(() => {
|
|
1149
|
+
if (prop.dbDefault !== undefined) {
|
|
1150
|
+
return {
|
|
1151
|
+
defaultTo: prop.dbDefault,
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
return {};
|
|
1155
|
+
})(),
|
|
1122
1156
|
// Decimal, Float 타입의 경우 precision, scale 추가
|
|
1123
1157
|
...(isDecimalProp(prop) || isFloatProp(prop)
|
|
1124
1158
|
? {
|
|
@@ -1286,7 +1320,14 @@ export class Migrator {
|
|
|
1286
1320
|
|
|
1287
1321
|
// defaultTo
|
|
1288
1322
|
if (column.defaultTo !== undefined) {
|
|
1289
|
-
|
|
1323
|
+
if (
|
|
1324
|
+
typeof column.defaultTo === "string" &&
|
|
1325
|
+
column.defaultTo.startsWith(`"`)
|
|
1326
|
+
) {
|
|
1327
|
+
chains.push(`defaultTo(${column.defaultTo})`);
|
|
1328
|
+
} else {
|
|
1329
|
+
chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);
|
|
1330
|
+
}
|
|
1290
1331
|
}
|
|
1291
1332
|
|
|
1292
1333
|
return `table.${chains.join(".")};`;
|
package/src/syncer/syncer.ts
CHANGED
|
@@ -159,7 +159,7 @@ export class Syncer {
|
|
|
159
159
|
);
|
|
160
160
|
|
|
161
161
|
// 현재 checksums
|
|
162
|
-
|
|
162
|
+
let currentChecksums = await this.getCurrentChecksums();
|
|
163
163
|
// 이전 checksums
|
|
164
164
|
const previousChecksums = await this.getPreviousChecksums();
|
|
165
165
|
|
|
@@ -190,12 +190,26 @@ export class Syncer {
|
|
|
190
190
|
// 변경된 파일들을 타입별로 분리하여 각 타입별 액션 처리
|
|
191
191
|
const diffTypes = Object.keys(diffGroups);
|
|
192
192
|
|
|
193
|
-
// 트리거: entity
|
|
193
|
+
// 트리거: entity, types
|
|
194
194
|
// 액션: 스키마 생성
|
|
195
|
-
if (diffTypes.includes("entity")) {
|
|
195
|
+
if (diffTypes.includes("entity") || diffTypes.includes("types")) {
|
|
196
196
|
console.log("// 액션: 스키마 생성");
|
|
197
|
-
const entityIds = this.getEntityIdFromPath(
|
|
197
|
+
const entityIds = this.getEntityIdFromPath([
|
|
198
|
+
...(diffGroups["entity"] ?? []),
|
|
199
|
+
...(diffGroups["types"] ?? []),
|
|
200
|
+
]);
|
|
198
201
|
await this.actionGenerateSchemas(entityIds);
|
|
202
|
+
|
|
203
|
+
// 타입이 변경된 경우 generated 싱크까지 동시에 처리 후 체크섬 갱신
|
|
204
|
+
if (diffTypes.includes("types")) {
|
|
205
|
+
diffGroups["generated"] = uniq([
|
|
206
|
+
...(diffGroups["generated"] ?? []),
|
|
207
|
+
...diffGroups["types"].map((p) =>
|
|
208
|
+
p.replace(".types.ts", ".generated.ts")
|
|
209
|
+
),
|
|
210
|
+
]);
|
|
211
|
+
currentChecksums = await this.getCurrentChecksums();
|
|
212
|
+
}
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
// 트리거: types, enums, generated 변경시
|
|
@@ -207,11 +221,13 @@ export class Syncer {
|
|
|
207
221
|
) {
|
|
208
222
|
console.log("// 액션: 파일 싱크 types / functions / generated");
|
|
209
223
|
|
|
210
|
-
const tsPaths =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
224
|
+
const tsPaths = uniq(
|
|
225
|
+
[
|
|
226
|
+
...(diffGroups["types"] ?? []),
|
|
227
|
+
...(diffGroups["functions"] ?? []),
|
|
228
|
+
...(diffGroups["generated"] ?? []),
|
|
229
|
+
].map((p) => p.replace("/dist/", "/src/").replace(".js", ".ts"))
|
|
230
|
+
);
|
|
215
231
|
await this.actionSyncFilesToTargets(tsPaths);
|
|
216
232
|
}
|
|
217
233
|
|
|
@@ -229,10 +245,12 @@ export class Syncer {
|
|
|
229
245
|
}
|
|
230
246
|
|
|
231
247
|
getEntityIdFromPath(filePaths: string[]): string[] {
|
|
232
|
-
return
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
248
|
+
return uniq(
|
|
249
|
+
filePaths.map((p) => {
|
|
250
|
+
const matched = p.match(/application\/(.+)\//);
|
|
251
|
+
return camelize(matched![1].replace(/\-/g, "_"));
|
|
252
|
+
})
|
|
253
|
+
);
|
|
236
254
|
}
|
|
237
255
|
|
|
238
256
|
async actionGenerateSchemas(entityIds: string[]): Promise<string[]> {
|
|
@@ -702,8 +720,10 @@ export class Syncer {
|
|
|
702
720
|
return this.models;
|
|
703
721
|
}
|
|
704
722
|
|
|
705
|
-
async autoloadTypes(
|
|
706
|
-
|
|
723
|
+
async autoloadTypes(
|
|
724
|
+
doRefresh: boolean = false
|
|
725
|
+
): Promise<{ [typeName: string]: z.ZodObject<any> }> {
|
|
726
|
+
if (!doRefresh && Object.keys(this.types).length > 0) {
|
|
707
727
|
return this.types;
|
|
708
728
|
}
|
|
709
729
|
|
|
@@ -716,7 +736,7 @@ export class Syncer {
|
|
|
716
736
|
const filePaths = (
|
|
717
737
|
await Promise.all(pathPatterns.map((pattern) => globAsync(pattern)))
|
|
718
738
|
).flat();
|
|
719
|
-
const modules = await importMultiple(filePaths);
|
|
739
|
+
const modules = await importMultiple(filePaths, doRefresh);
|
|
720
740
|
const functions = modules
|
|
721
741
|
.map(({ imported }) => Object.entries(imported))
|
|
722
742
|
.flat();
|
|
@@ -917,10 +937,7 @@ export class Syncer {
|
|
|
917
937
|
};
|
|
918
938
|
|
|
919
939
|
// 키 children
|
|
920
|
-
|
|
921
|
-
// if (key === "entity") {
|
|
922
|
-
// keys = ["entity", "init_generated", "init_types"];
|
|
923
|
-
// }
|
|
940
|
+
const keys: TemplateKey[] = [key];
|
|
924
941
|
|
|
925
942
|
// 템플릿 렌더
|
|
926
943
|
const pathAndCodes = (
|
|
@@ -940,27 +957,30 @@ export class Syncer {
|
|
|
940
957
|
- 옵션3 : 메인 파일만 그대로 두고, 파생 파일은 전부 생성함 => 이게 맞지 않나?
|
|
941
958
|
*/
|
|
942
959
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
"이미 경로에 모든 파일이 존재합니다."
|
|
962
|
-
);
|
|
960
|
+
const filteredPathAndCodes: PathAndCode[] = (() => {
|
|
961
|
+
if (generateOptions.overwrite === true) {
|
|
962
|
+
return pathAndCodes;
|
|
963
|
+
} else {
|
|
964
|
+
return pathAndCodes.filter((pathAndCode, index) => {
|
|
965
|
+
if (index === 0) {
|
|
966
|
+
const { targets } = Sonamu.config.sync;
|
|
967
|
+
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
968
|
+
const dstFilePaths = targets.map((target) =>
|
|
969
|
+
filePath.replace("/:target/", `/${target}/`)
|
|
970
|
+
);
|
|
971
|
+
return dstFilePaths.every(
|
|
972
|
+
(dstPath) => existsSync(dstPath) === false
|
|
973
|
+
);
|
|
974
|
+
} else {
|
|
975
|
+
return true;
|
|
976
|
+
}
|
|
977
|
+
});
|
|
963
978
|
}
|
|
979
|
+
})();
|
|
980
|
+
if (filteredPathAndCodes.length === 0) {
|
|
981
|
+
throw new AlreadyProcessedException(
|
|
982
|
+
"이미 경로에 모든 파일이 존재합니다."
|
|
983
|
+
);
|
|
964
984
|
}
|
|
965
985
|
|
|
966
986
|
return Promise.all(
|
|
@@ -970,6 +990,24 @@ export class Syncer {
|
|
|
970
990
|
);
|
|
971
991
|
}
|
|
972
992
|
|
|
993
|
+
checkExistsGenCode(
|
|
994
|
+
entityId: string,
|
|
995
|
+
templateKey: TemplateKey,
|
|
996
|
+
enumId?: string
|
|
997
|
+
): { subPath: string; fullPath: string; isExists: boolean } {
|
|
998
|
+
const { target, path: genPath } = this.getTemplate(
|
|
999
|
+
templateKey
|
|
1000
|
+
).getTargetAndPath(EntityManager.getNamesFromId(entityId), enumId);
|
|
1001
|
+
|
|
1002
|
+
const fullPath = path.join(Sonamu.appRootPath, target, genPath);
|
|
1003
|
+
const subPath = path.join(target, genPath);
|
|
1004
|
+
return {
|
|
1005
|
+
subPath,
|
|
1006
|
+
fullPath,
|
|
1007
|
+
isExists: existsSync(fullPath),
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
|
|
973
1011
|
checkExists(
|
|
974
1012
|
entityId: string,
|
|
975
1013
|
enums: {
|
|
@@ -1296,12 +1334,14 @@ export class Syncer {
|
|
|
1296
1334
|
await EntityManager.reload();
|
|
1297
1335
|
|
|
1298
1336
|
// generate schemas
|
|
1299
|
-
await this.actionGenerateSchemas([entityId]);
|
|
1337
|
+
await this.actionGenerateSchemas([parentId ?? entityId]);
|
|
1300
1338
|
|
|
1301
1339
|
// generate types
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1340
|
+
if (parentId === undefined) {
|
|
1341
|
+
await this.generateTemplate("init_types", {
|
|
1342
|
+
entityId,
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1305
1345
|
}
|
|
1306
1346
|
|
|
1307
1347
|
async delEntity(entityId: string): Promise<{ delPaths: string[] }> {
|
|
@@ -7,10 +7,10 @@ export class Template__entity extends Template {
|
|
|
7
7
|
super("entity");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
getTargetAndPath(names: EntityNamesRecord) {
|
|
10
|
+
getTargetAndPath(names: EntityNamesRecord, parentNames?: EntityNamesRecord) {
|
|
11
11
|
return {
|
|
12
12
|
target: "api/src/application",
|
|
13
|
-
path: `${names.fs}/${names.fs}.entity.json`,
|
|
13
|
+
path: `${(parentNames ?? names).fs}/${names.fs}.entity.json`,
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -18,30 +18,63 @@ export class Template__entity extends Template {
|
|
|
18
18
|
const { entityId, title, parentId, table } = options;
|
|
19
19
|
const names = EntityManager.getNamesFromId(entityId);
|
|
20
20
|
|
|
21
|
+
const parent = (() => {
|
|
22
|
+
if (parentId) {
|
|
23
|
+
return {
|
|
24
|
+
names: EntityManager.getNamesFromId(parentId),
|
|
25
|
+
entity: EntityManager.get(parentId),
|
|
26
|
+
};
|
|
27
|
+
} else {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
})();
|
|
31
|
+
|
|
21
32
|
return {
|
|
22
|
-
...this.getTargetAndPath(names),
|
|
33
|
+
...this.getTargetAndPath(names, parent?.names ?? names),
|
|
23
34
|
body: JSON.stringify({
|
|
24
35
|
id: entityId,
|
|
25
36
|
title: title ?? entityId,
|
|
26
37
|
parentId,
|
|
27
38
|
table: table ?? names.fsPlural.replace(/\-/g, "_"),
|
|
28
39
|
props: [
|
|
29
|
-
{ name: "id", type: "integer", unsigned: true },
|
|
40
|
+
{ name: "id", type: "integer", unsigned: true, desc: "ID" },
|
|
41
|
+
...(parent
|
|
42
|
+
? [
|
|
43
|
+
{
|
|
44
|
+
type: "relation",
|
|
45
|
+
name: parent.names.camel,
|
|
46
|
+
relationType: "BelongsToOne",
|
|
47
|
+
with: parentId,
|
|
48
|
+
onUpdate: "CASCADE",
|
|
49
|
+
onDelete: "CASCADE",
|
|
50
|
+
desc: parent.entity.title,
|
|
51
|
+
},
|
|
52
|
+
]
|
|
53
|
+
: []),
|
|
30
54
|
{
|
|
31
55
|
name: "created_at",
|
|
32
56
|
type: "timestamp",
|
|
57
|
+
desc: "등록일시",
|
|
33
58
|
dbDefault: "CURRENT_TIMESTAMP",
|
|
34
59
|
},
|
|
35
60
|
],
|
|
36
61
|
indexes: [],
|
|
37
62
|
subsets: {
|
|
38
|
-
|
|
63
|
+
...(parentId
|
|
64
|
+
? {}
|
|
65
|
+
: {
|
|
66
|
+
A: ["id", "created_at"],
|
|
67
|
+
}),
|
|
39
68
|
},
|
|
40
69
|
enums: {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
70
|
+
...(parentId
|
|
71
|
+
? {}
|
|
72
|
+
: {
|
|
73
|
+
[`${names.capital}OrderBy`]: {
|
|
74
|
+
"id-desc": "ID최신순",
|
|
75
|
+
},
|
|
76
|
+
[`${names.capital}SearchField`]: { id: "ID" },
|
|
77
|
+
}),
|
|
45
78
|
},
|
|
46
79
|
}).trim(),
|
|
47
80
|
importKeys: [],
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { EntityManager, EntityNamesRecord } from "../entity/entity-manager";
|
|
10
10
|
import { Entity } from "../entity/entity";
|
|
11
11
|
import { EntityPropNode, SubsetQuery } from "../types/types";
|
|
12
|
-
import { propNodeToZodTypeDef } from "../api/code-converters";
|
|
12
|
+
import { propNodeToZodTypeDef, zodTypeToZodCode } from "../api/code-converters";
|
|
13
13
|
import { Template } from "./base-template";
|
|
14
14
|
|
|
15
15
|
export class Template__generated extends Template {
|
|
@@ -33,7 +33,7 @@ export class Template__generated extends Template {
|
|
|
33
33
|
...(entity.parentId === undefined
|
|
34
34
|
? [
|
|
35
35
|
this.getBaseListParamsTypeSource(entity),
|
|
36
|
-
this.getSubsetTypeSource(entity)
|
|
36
|
+
this.getSubsetTypeSource(entity)!,
|
|
37
37
|
]
|
|
38
38
|
: []),
|
|
39
39
|
].reduce(
|
|
@@ -52,6 +52,31 @@ export class Template__generated extends Template {
|
|
|
52
52
|
}
|
|
53
53
|
);
|
|
54
54
|
|
|
55
|
+
// .types.ts의 타입을 참조하는 경우 순환참조(상호참조)가 발생하므로 해당 타입을 가져와 인라인 처리
|
|
56
|
+
const entityTypeKeys = Object.keys(entity.types);
|
|
57
|
+
const cdImportKeys = uniq(typeSource.importKeys).filter((importKey) =>
|
|
58
|
+
entityTypeKeys.includes(importKey)
|
|
59
|
+
);
|
|
60
|
+
if (cdImportKeys.length > 0) {
|
|
61
|
+
typeSource.lines = [
|
|
62
|
+
...cdImportKeys
|
|
63
|
+
.map((importKey) => [
|
|
64
|
+
`// Imported CustomScalar: ${importKey}`,
|
|
65
|
+
`const ${importKey} = ${zodTypeToZodCode(
|
|
66
|
+
entity.types[importKey]
|
|
67
|
+
)};`,
|
|
68
|
+
`type ${importKey} = z.infer<typeof ${importKey}>`,
|
|
69
|
+
"",
|
|
70
|
+
])
|
|
71
|
+
.flat(),
|
|
72
|
+
"",
|
|
73
|
+
...typeSource.lines,
|
|
74
|
+
];
|
|
75
|
+
typeSource.importKeys = typeSource.importKeys.filter(
|
|
76
|
+
(importKey) => !cdImportKeys.includes(importKey)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
55
80
|
// targetAndPath
|
|
56
81
|
const names = EntityManager.getNamesFromId(entityId);
|
|
57
82
|
const targetAndPath = this.getTargetAndPath(names);
|
package/src/types/types.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type CommonProp = {
|
|
|
41
41
|
nullable?: boolean;
|
|
42
42
|
toFilter?: true;
|
|
43
43
|
desc?: string;
|
|
44
|
-
dbDefault?: string
|
|
44
|
+
dbDefault?: string;
|
|
45
45
|
};
|
|
46
46
|
export type IntegerProp = CommonProp & {
|
|
47
47
|
type: "integer";
|
|
@@ -73,6 +73,8 @@ export type FloatProp = CommonProp & {
|
|
|
73
73
|
export type DoubleProp = CommonProp & {
|
|
74
74
|
type: "double";
|
|
75
75
|
unsigned?: true;
|
|
76
|
+
precision: number;
|
|
77
|
+
scale: number;
|
|
76
78
|
};
|
|
77
79
|
export type DecimalProp = CommonProp & {
|
|
78
80
|
type: "decimal";
|
|
@@ -113,7 +115,6 @@ export type RelationType =
|
|
|
113
115
|
| "ManyToMany"
|
|
114
116
|
| "OneToOne";
|
|
115
117
|
export type RelationOn =
|
|
116
|
-
| "UPDATE"
|
|
117
118
|
| "CASCADE"
|
|
118
119
|
| "SET NULL"
|
|
119
120
|
| "NO ACTION"
|
|
@@ -394,7 +395,7 @@ export type MigrationColumn = {
|
|
|
394
395
|
nullable: boolean;
|
|
395
396
|
unsigned?: boolean;
|
|
396
397
|
length?: number;
|
|
397
|
-
defaultTo?: string
|
|
398
|
+
defaultTo?: string;
|
|
398
399
|
precision?: number;
|
|
399
400
|
scale?: number;
|
|
400
401
|
};
|
package/src/utils/utils.ts
CHANGED
|
@@ -14,11 +14,15 @@ export function globAsync(pathPattern: string): Promise<string[]> {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
export async function importMultiple(
|
|
17
|
-
filePaths: string[]
|
|
17
|
+
filePaths: string[],
|
|
18
|
+
doRefresh: boolean = false
|
|
18
19
|
): Promise<{ filePath: string; imported: any }[]> {
|
|
19
20
|
return Promise.all(
|
|
20
21
|
filePaths.map(async (filePath) => {
|
|
21
22
|
const importPath = "./" + path.relative(__dirname, filePath);
|
|
23
|
+
if (doRefresh) {
|
|
24
|
+
delete require.cache[require.resolve(importPath)];
|
|
25
|
+
}
|
|
22
26
|
const imported = await import(importPath);
|
|
23
27
|
return {
|
|
24
28
|
filePath,
|