sonamu 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +38 -37
- package/dist/database/base-model.js.map +1 -1
- package/dist/entity/migrator.d.ts.map +1 -1
- package/dist/entity/migrator.js +10 -23
- package/dist/entity/migrator.js.map +1 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +1 -1
- package/dist/syncer/syncer.js.map +1 -1
- package/dist/templates/generated.template.d.ts.map +1 -1
- package/dist/templates/generated.template.js +2 -24
- package/dist/templates/generated.template.js.map +1 -1
- package/dist/templates/view_list.template.d.ts.map +1 -1
- package/dist/templates/view_list.template.js +1 -1
- package/dist/templates/view_list.template.js.map +1 -1
- package/dist/testing/fixture-manager.js.map +1 -1
- package/dist/types/types.d.ts +2 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +3 -1
- 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/model.js +1 -4
- package/dist/utils/model.js.map +1 -1
- package/package.json +1 -1
- package/src/database/base-model.ts +45 -41
- package/src/entity/migrator.ts +12 -29
- package/src/shared/web.shared.ts.txt +2 -5
- package/src/syncer/syncer.ts +2 -1
- package/src/templates/generated.template.ts +2 -25
- package/src/templates/view_list.template.ts +1 -1
- package/src/testing/fixture-manager.ts +1 -1
- package/src/types/types.ts +4 -0
- package/src/utils/model.ts +2 -2
|
@@ -214,6 +214,8 @@ export class BaseModelClass {
|
|
|
214
214
|
}> {
|
|
215
215
|
const db = this.getDB(subset.startsWith("A") ? "w" : "r");
|
|
216
216
|
baseTable = baseTable ?? pluralize(underscore(this.modelName));
|
|
217
|
+
const queryMode =
|
|
218
|
+
params.queryMode ?? (params.id !== undefined ? "list" : "both");
|
|
217
219
|
|
|
218
220
|
const { select, virtual, joins, loaders } = subsetQuery;
|
|
219
221
|
const qb = build({
|
|
@@ -239,55 +241,55 @@ export class BaseModelClass {
|
|
|
239
241
|
}
|
|
240
242
|
});
|
|
241
243
|
|
|
242
|
-
//
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const [, matched] =
|
|
247
|
-
clonedQb
|
|
248
|
-
.toQuery()
|
|
249
|
-
.toLowerCase()
|
|
250
|
-
.match(/select (distinct .+) from/) ?? [];
|
|
251
|
-
if (matched) {
|
|
252
|
-
countQuery = clonedQb
|
|
253
|
-
.clear("select")
|
|
254
|
-
.select(db.raw(`COUNT(${matched}) as total`));
|
|
255
|
-
} else {
|
|
256
|
-
countQuery = clonedQb.clear("select").count("*", { as: "total" });
|
|
244
|
+
// listQuery
|
|
245
|
+
const rows = await (async () => {
|
|
246
|
+
if (queryMode === "count") {
|
|
247
|
+
return [];
|
|
257
248
|
}
|
|
258
|
-
}
|
|
259
249
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
250
|
+
// limit, offset
|
|
251
|
+
if (params.num !== 0) {
|
|
252
|
+
qb.limit(params.num!);
|
|
253
|
+
qb.offset(params.num! * (params.page! - 1));
|
|
254
|
+
}
|
|
265
255
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const listQuery = qb.clone();
|
|
256
|
+
// select, rows
|
|
257
|
+
const listQuery = qb.clone().select(select);
|
|
269
258
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
259
|
+
let rows = await listQuery;
|
|
260
|
+
// debug: listQuery
|
|
261
|
+
if (debug === true || debug === "list") {
|
|
262
|
+
console.debug(
|
|
263
|
+
"DEBUG: list query",
|
|
264
|
+
chalk.blue(listQuery.toQuery().toString())
|
|
265
|
+
);
|
|
266
|
+
}
|
|
277
267
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
268
|
+
rows = await this.useLoaders(db, rows, loaders);
|
|
269
|
+
rows = this.hydrate(rows);
|
|
270
|
+
return rows;
|
|
271
|
+
})();
|
|
282
272
|
|
|
283
273
|
// countQuery
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if (countResult && countResult[0] && countResult[0].total) {
|
|
288
|
-
total = countResult[0].total;
|
|
274
|
+
const total = await (async () => {
|
|
275
|
+
if (queryMode === "list") {
|
|
276
|
+
return undefined;
|
|
289
277
|
}
|
|
290
278
|
|
|
279
|
+
const clonedQb = qb.clone().clear("order");
|
|
280
|
+
const [, matched] =
|
|
281
|
+
clonedQb
|
|
282
|
+
.toQuery()
|
|
283
|
+
.toLowerCase()
|
|
284
|
+
.match(/select (distinct .+) from/) ?? [];
|
|
285
|
+
const countQuery = matched
|
|
286
|
+
? clonedQb
|
|
287
|
+
.clear("select")
|
|
288
|
+
.select(db.raw(`COUNT(${matched}) as total`))
|
|
289
|
+
.first()
|
|
290
|
+
: clonedQb.clear("select").count("*", { as: "total" }).first();
|
|
291
|
+
const countRow: { total?: number } = await countQuery;
|
|
292
|
+
|
|
291
293
|
// debug: countQuery
|
|
292
294
|
if (debug === true || debug === "count") {
|
|
293
295
|
console.debug(
|
|
@@ -295,7 +297,9 @@ export class BaseModelClass {
|
|
|
295
297
|
chalk.blue(countQuery.toQuery().toString())
|
|
296
298
|
);
|
|
297
299
|
}
|
|
298
|
-
|
|
300
|
+
|
|
301
|
+
return countRow?.total ?? 0;
|
|
302
|
+
})();
|
|
299
303
|
|
|
300
304
|
return { rows, total, subsetQuery, qb };
|
|
301
305
|
}
|
package/src/entity/migrator.ts
CHANGED
|
@@ -840,7 +840,7 @@ export class Migrator {
|
|
|
840
840
|
).map((f) => replaceNoActionOnMySQL(f));
|
|
841
841
|
|
|
842
842
|
if (equal(entityForeigns, dbForeigns) === false) {
|
|
843
|
-
console.dir({ entityForeigns, dbForeigns }, { depth: null });
|
|
843
|
+
// console.dir({ entityForeigns, dbForeigns }, { depth: null });
|
|
844
844
|
return this.generateAlterCode_Foreigns(
|
|
845
845
|
entitySet.table,
|
|
846
846
|
entityForeigns,
|
|
@@ -1076,40 +1076,23 @@ export class Migrator {
|
|
|
1076
1076
|
const foreignKeys = (matched ?? []).map((line: string) => {
|
|
1077
1077
|
// 해당 라인을 정규식으로 파싱
|
|
1078
1078
|
const matched = line.match(
|
|
1079
|
-
/CONSTRAINT `(.+)` FOREIGN KEY \(`(.+)`\) REFERENCES `(.+)` \(`(.+)`\)( ON
|
|
1079
|
+
/CONSTRAINT `(.+)` FOREIGN KEY \(`(.+)`\) REFERENCES `(.+)` \(`(.+)`\)( ON [A-Z ]+)*/
|
|
1080
1080
|
);
|
|
1081
1081
|
if (!matched) {
|
|
1082
1082
|
throw new Error(`인식할 수 없는 FOREIGN KEY CONSTRAINT ${line}`);
|
|
1083
1083
|
}
|
|
1084
|
-
const [, keyName, from, referencesTable, referencesField,
|
|
1084
|
+
const [, keyName, from, referencesTable, referencesField, onClause] =
|
|
1085
1085
|
matched;
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
const { onDelete, onUpdate } = (() => {
|
|
1089
|
-
// ON Clause가 둘다 있는 경우
|
|
1090
|
-
if (
|
|
1091
|
-
onClause.includes("ON DELETE") &&
|
|
1092
|
-
onClause.includes("ON UPDATE")
|
|
1093
|
-
) {
|
|
1094
|
-
const [, onDelete, onUpdate] = onClause.match(
|
|
1095
|
-
/ON DELETE ([A-Z ]+) ON UPDATE ([A-Z ]+)/
|
|
1096
|
-
)!;
|
|
1097
|
-
return {
|
|
1098
|
-
onDelete,
|
|
1099
|
-
onUpdate,
|
|
1100
|
-
};
|
|
1101
|
-
}
|
|
1086
|
+
// console.debug({ tableName, line, onClause });
|
|
1102
1087
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
};
|
|
1112
|
-
})();
|
|
1088
|
+
const [onUpdateFull, _onUpdate] =
|
|
1089
|
+
(onClause ?? "").match(/ON UPDATE ([A-Z ]+)$/) ?? [];
|
|
1090
|
+
const onUpdate = _onUpdate ?? "NO ACTION";
|
|
1091
|
+
|
|
1092
|
+
const onDelete =
|
|
1093
|
+
(onClause ?? "")
|
|
1094
|
+
.replace(onUpdateFull ?? "", "")
|
|
1095
|
+
.match(/ON DELETE ([A-Z ]+) /)?.[1] ?? "NO ACTION";
|
|
1113
1096
|
|
|
1114
1097
|
return {
|
|
1115
1098
|
keyName,
|
|
@@ -55,11 +55,8 @@ export type ListResult<T> = {
|
|
|
55
55
|
rows: T[];
|
|
56
56
|
total?: number;
|
|
57
57
|
};
|
|
58
|
-
|
|
59
|
-
export type
|
|
60
|
-
[key in T]: { [lang in L]: string };
|
|
61
|
-
};
|
|
62
|
-
export type EnumsLabelKo<T extends string> = EnumsLabel<T, "ko">;
|
|
58
|
+
export const SonamuQueryMode = z.enum(["both", "list", "count"]);
|
|
59
|
+
export type SonamuQueryMode = z.infer<typeof SonamuQueryMode>;
|
|
63
60
|
|
|
64
61
|
/*
|
|
65
62
|
SWR
|
package/src/syncer/syncer.ts
CHANGED
|
@@ -578,6 +578,8 @@ export class Syncer {
|
|
|
578
578
|
return this.resolveParamDec({
|
|
579
579
|
name: (member as ts.PropertySignature).name as ts.Identifier,
|
|
580
580
|
type: (member as ts.PropertySignature).type as ts.TypeNode,
|
|
581
|
+
optional:
|
|
582
|
+
(member as ts.PropertySignature).questionToken !== undefined,
|
|
581
583
|
});
|
|
582
584
|
}
|
|
583
585
|
}),
|
|
@@ -971,7 +973,6 @@ export class Syncer {
|
|
|
971
973
|
}
|
|
972
974
|
})();
|
|
973
975
|
if (filteredPathAndCodes.length === 0) {
|
|
974
|
-
console.log("요거란 말이지?");
|
|
975
976
|
throw new AlreadyProcessedException(
|
|
976
977
|
"이미 경로에 모든 파일이 존재합니다."
|
|
977
978
|
);
|
|
@@ -115,6 +115,7 @@ export class Template__generated extends Template {
|
|
|
115
115
|
"zArrayable",
|
|
116
116
|
"SQLDateTimeString",
|
|
117
117
|
"SubsetQuery",
|
|
118
|
+
"SonamuQueryMode",
|
|
118
119
|
].filter((mod) => body.includes(mod));
|
|
119
120
|
|
|
120
121
|
return {
|
|
@@ -210,7 +211,7 @@ z.object({
|
|
|
210
211
|
search: ${entity.id}SearchField,
|
|
211
212
|
keyword: z.string(),
|
|
212
213
|
orderBy: ${entity.id}OrderBy,
|
|
213
|
-
|
|
214
|
+
queryMode: SonamuQueryMode,
|
|
214
215
|
id: zArrayable(z.number().int().positive()),${filterBody}
|
|
215
216
|
}).partial();
|
|
216
217
|
`.trim();
|
|
@@ -237,7 +238,6 @@ z.object({
|
|
|
237
238
|
const subsetKeys = Object.keys(entity.subsets);
|
|
238
239
|
const importKeys: string[] = [];
|
|
239
240
|
const lines: string[] = [
|
|
240
|
-
// `// Subsets: ${entity.id}`,
|
|
241
241
|
...subsetKeys
|
|
242
242
|
.map((subsetKey) => {
|
|
243
243
|
// 서브셋에서 FieldExpr[] 가져옴
|
|
@@ -271,31 +271,8 @@ z.object({
|
|
|
271
271
|
.join(",")}]);`,
|
|
272
272
|
`export type ${entity.names.module}SubsetKey = z.infer<typeof ${entity.names.module}SubsetKey>`,
|
|
273
273
|
"",
|
|
274
|
-
// "/* BEGIN- Server-side Only */",
|
|
275
|
-
// // `import { SubsetQuery } from "sonamu";`,
|
|
276
|
-
// `export const ${camelize(entity.id, true)}SubsetQueries:{ [key in ${
|
|
277
|
-
// entity.names.module
|
|
278
|
-
// }SubsetKey]: SubsetQuery} = ${JSON.stringify(subsetQueryObject)}`,
|
|
279
|
-
// "",
|
|
280
274
|
];
|
|
281
275
|
|
|
282
|
-
// ServerSide Only
|
|
283
|
-
// const subsetQueryObject = subsetKeys.reduce(
|
|
284
|
-
// (r, subsetKey) => {
|
|
285
|
-
// const subsetQuery = entity.getSubsetQuery(subsetKey);
|
|
286
|
-
// r[subsetKey] = subsetQuery;
|
|
287
|
-
// return r;
|
|
288
|
-
// },
|
|
289
|
-
// {} as {
|
|
290
|
-
// [key: string]: SubsetQuery;
|
|
291
|
-
// }
|
|
292
|
-
// );
|
|
293
|
-
// const lines2: string[] = [
|
|
294
|
-
// `export const ${camelize(entity.id, true)}SubsetQueries:{ [key in ${
|
|
295
|
-
// entity.names.module
|
|
296
|
-
// }SubsetKey]: SubsetQuery} = ${JSON.stringify(subsetQueryObject)}`,
|
|
297
|
-
// ];
|
|
298
|
-
|
|
299
276
|
return {
|
|
300
277
|
label: `Subsets: ${entity.id}`,
|
|
301
278
|
lines,
|
|
@@ -251,6 +251,7 @@ export class Template__view_list extends Template {
|
|
|
251
251
|
.filter(
|
|
252
252
|
(col) =>
|
|
253
253
|
col.name !== "id" &&
|
|
254
|
+
col.name !== "queryMode" &&
|
|
254
255
|
(["enums", "number-id"].includes(col.renderType) ||
|
|
255
256
|
col.name.endsWith("_id"))
|
|
256
257
|
)
|
|
@@ -576,7 +577,6 @@ export function getEnumInfoFromColName(
|
|
|
576
577
|
underscore(entityId) + "_" + underscore(colName),
|
|
577
578
|
false
|
|
578
579
|
);
|
|
579
|
-
console.log({ idCandidate });
|
|
580
580
|
try {
|
|
581
581
|
const targetEntityNames = EntityManager.getNamesFromId(entityId);
|
|
582
582
|
return {
|
|
@@ -67,7 +67,7 @@ export class FixtureManagerClass {
|
|
|
67
67
|
const [tables] = await this.tdb.raw(
|
|
68
68
|
"SHOW TABLE STATUS WHERE Engine IS NOT NULL"
|
|
69
69
|
);
|
|
70
|
-
return tables.map((tableInfo: any) => tableInfo["Name"]);
|
|
70
|
+
return tables.map((tableInfo: any) => tableInfo["Name"] as string);
|
|
71
71
|
})();
|
|
72
72
|
|
|
73
73
|
await this.tdb.raw(`SET FOREIGN_KEY_CHECKS = 0`);
|
package/src/types/types.ts
CHANGED
|
@@ -359,6 +359,10 @@ export type SubsetQuery = {
|
|
|
359
359
|
loaders: SubsetLoader[];
|
|
360
360
|
};
|
|
361
361
|
|
|
362
|
+
/* BaseModel */
|
|
363
|
+
export const SonamuQueryMode = z.enum(["both", "list", "count"]);
|
|
364
|
+
export type SonamuQueryMode = z.infer<typeof SonamuQueryMode>;
|
|
365
|
+
|
|
362
366
|
/* Knex Migration */
|
|
363
367
|
export type KnexError = {
|
|
364
368
|
code: string;
|
package/src/utils/model.ts
CHANGED
|
@@ -24,10 +24,10 @@ export function objToMap<T>(obj: { [k: string]: T }) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export
|
|
27
|
+
export interface BaseListParams {
|
|
28
28
|
id?: number | number[];
|
|
29
29
|
num?: number;
|
|
30
30
|
page?: number;
|
|
31
31
|
keyword?: string;
|
|
32
|
-
|
|
32
|
+
queryMode?: "list" | "count" | "both";
|
|
33
33
|
}
|