sonamu 0.2.36 → 0.2.38
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 +2117 -86
- package/dist/api/decorators.js +5 -2
- package/dist/api/decorators.js.map +1 -1
- package/dist/api/sonamu.js +3 -3
- package/dist/api/sonamu.js.map +1 -1
- package/dist/bin/cli-wrapper.d.ts +3 -0
- package/dist/bin/cli-wrapper.d.ts.map +1 -0
- package/dist/bin/cli-wrapper.js +27 -0
- package/dist/bin/cli-wrapper.js.map +1 -0
- package/dist/bin/cli.js +10 -10
- package/dist/bin/cli.js.map +1 -1
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +14 -13
- package/dist/database/base-model.js.map +1 -1
- package/dist/database/db.js +1 -1
- package/dist/database/db.js.map +1 -1
- package/dist/database/upsert-builder.js +8 -5
- package/dist/database/upsert-builder.js.map +1 -1
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +14 -12
- package/dist/entity/entity-manager.js.map +1 -1
- package/dist/entity/entity-utils.js +5 -2
- package/dist/entity/entity-utils.js.map +1 -1
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +20 -18
- package/dist/entity/entity.js.map +1 -1
- package/dist/entity/migrator.d.ts.map +1 -1
- package/dist/entity/migrator.js +59 -55
- package/dist/entity/migrator.js.map +1 -1
- package/dist/smd/smd-manager.d.ts.map +1 -1
- package/dist/smd/smd-manager.js +13 -9
- package/dist/smd/smd-manager.js.map +1 -1
- package/dist/smd/smd.d.ts.map +1 -1
- package/dist/smd/smd.js +13 -14
- package/dist/smd/smd.js.map +1 -1
- package/dist/syncer/syncer.d.ts +1 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +68 -67
- package/dist/syncer/syncer.js.map +1 -1
- package/dist/templates/generated.template.js +6 -3
- package/dist/templates/generated.template.js.map +1 -1
- package/dist/templates/generated_sso.template.js +7 -4
- package/dist/templates/generated_sso.template.js.map +1 -1
- package/dist/templates/service.template.js +13 -10
- package/dist/templates/service.template.js.map +1 -1
- package/dist/templates/view_enums_dropdown.template.js +5 -2
- package/dist/templates/view_enums_dropdown.template.js.map +1 -1
- package/dist/templates/view_form.template.d.ts.map +1 -1
- package/dist/templates/view_form.template.js +7 -4
- package/dist/templates/view_form.template.js.map +1 -1
- package/dist/templates/view_id_async_select.template.js.map +1 -1
- package/dist/templates/view_list.template.js +10 -7
- package/dist/templates/view_list.template.js.map +1 -1
- package/dist/testing/fixture-manager.js +3 -3
- package/dist/testing/fixture-manager.js.map +1 -1
- package/dist/utils/sql-parser.js +5 -2
- package/dist/utils/sql-parser.js.map +1 -1
- package/dist/utils/utils.js +2 -2
- package/dist/utils/utils.js.map +1 -1
- package/package.json +19 -5
- package/src/api/decorators.ts +3 -3
- package/src/api/sonamu.ts +3 -3
- package/src/bin/cli-wrapper.ts +34 -0
- package/src/bin/cli.ts +10 -16
- package/src/database/base-model.ts +18 -15
- package/src/database/db.ts +1 -1
- package/src/database/upsert-builder.ts +5 -5
- package/src/entity/entity-manager.ts +14 -12
- package/src/entity/entity-utils.ts +2 -2
- package/src/entity/entity.ts +13 -11
- package/src/entity/migrator.ts +73 -85
- package/src/smd/smd-manager.ts +13 -9
- package/src/smd/smd.ts +10 -11
- package/src/syncer/syncer.ts +44 -44
- package/src/templates/generated.template.ts +3 -3
- package/src/templates/generated_sso.template.ts +4 -4
- package/src/templates/service.template.ts +10 -10
- package/src/templates/view_enums_dropdown.template.ts +2 -2
- package/src/templates/view_form.template.ts +36 -33
- package/src/templates/view_id_async_select.template.ts +4 -4
- package/src/templates/view_list.template.ts +18 -18
- package/src/testing/fixture-manager.ts +3 -3
- package/src/utils/sql-parser.ts +2 -2
- package/src/utils/utils.ts +2 -2
- package/tsup.config.js +21 -0
package/package.json
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonamu",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.38",
|
|
4
4
|
"description": "Sonamu — TypeScript Fullstack API Framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
7
7
|
"framework",
|
|
8
8
|
"orm"
|
|
9
9
|
],
|
|
10
|
-
"
|
|
11
|
-
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"module": "./dist/index.mjs",
|
|
12
24
|
"scripts": {
|
|
13
|
-
"dev": "yarn tsc -w -p ./tsconfig.json"
|
|
25
|
+
"dev": "yarn tsc -w -p ./tsconfig.json",
|
|
26
|
+
"build": "tsup --config ./tsup.config.js"
|
|
14
27
|
},
|
|
15
28
|
"license": "MIT",
|
|
16
29
|
"author": {
|
|
@@ -22,7 +35,7 @@
|
|
|
22
35
|
"type": "git",
|
|
23
36
|
"url": "https://github.com/ping-alive/sonamu.git"
|
|
24
37
|
},
|
|
25
|
-
"bin": "./dist/bin/cli.
|
|
38
|
+
"bin": "./dist/bin/cli-wrapper.mjs",
|
|
26
39
|
"dependencies": {
|
|
27
40
|
"chalk": "^4.1.2",
|
|
28
41
|
"dotenv": "^16.0.2",
|
|
@@ -55,6 +68,7 @@
|
|
|
55
68
|
"@types/uuid": "^8.3.4",
|
|
56
69
|
"prettier": "^3.2.5",
|
|
57
70
|
"source-map-support": "^0.5.21",
|
|
71
|
+
"tsup": "^8.1.0",
|
|
58
72
|
"typescript": "^5.2.2"
|
|
59
73
|
},
|
|
60
74
|
"peerDependencies": {
|
package/src/api/decorators.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HTTPMethods } from "fastify";
|
|
2
|
-
import
|
|
2
|
+
import inflection from "inflection";
|
|
3
3
|
import { ApiParam, ApiParamType } from "../types/types";
|
|
4
4
|
|
|
5
5
|
export type ServiceClient =
|
|
@@ -49,10 +49,10 @@ export function api(options: ApiDecoratorOptions = {}) {
|
|
|
49
49
|
return function (target: Object, propertyKey: string) {
|
|
50
50
|
const modelName = target.constructor.name.match(/(.+)Class$/)![1];
|
|
51
51
|
const methodName = propertyKey;
|
|
52
|
-
const defaultPath = `/${camelize(
|
|
52
|
+
const defaultPath = `/${inflection.camelize(
|
|
53
53
|
modelName.replace(/Model$/, ""),
|
|
54
54
|
true
|
|
55
|
-
)}/${camelize(propertyKey, true)}`;
|
|
55
|
+
)}/${inflection.camelize(propertyKey, true)}`;
|
|
56
56
|
|
|
57
57
|
const api = {
|
|
58
58
|
modelName,
|
package/src/api/sonamu.ts
CHANGED
|
@@ -14,7 +14,7 @@ import { DB, SonamuDBConfig } from "../database/db";
|
|
|
14
14
|
import { BaseModel } from "../database/base-model";
|
|
15
15
|
import { findApiRootPath } from "../utils/utils";
|
|
16
16
|
import path from "path";
|
|
17
|
-
import
|
|
17
|
+
import fs from "fs-extra";
|
|
18
18
|
import { ApiDecoratorOptions } from "./decorators";
|
|
19
19
|
|
|
20
20
|
export type SonamuConfig = {
|
|
@@ -128,11 +128,11 @@ class SonamuClass {
|
|
|
128
128
|
|
|
129
129
|
this.apiRootPath = apiRootPath ?? (await findApiRootPath());
|
|
130
130
|
const configPath = path.join(this.apiRootPath, "sonamu.config.json");
|
|
131
|
-
if (existsSync(configPath) === false) {
|
|
131
|
+
if (fs.existsSync(configPath) === false) {
|
|
132
132
|
throw new Error(`Cannot find sonamu.config.json in ${configPath}`);
|
|
133
133
|
}
|
|
134
134
|
this.config = JSON.parse(
|
|
135
|
-
readFileSync(configPath).toString()
|
|
135
|
+
fs.readFileSync(configPath).toString()
|
|
136
136
|
) as SonamuConfig;
|
|
137
137
|
|
|
138
138
|
// DB 로드
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env ts-node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "child_process";
|
|
4
|
+
import { resolve } from "path";
|
|
5
|
+
import { existsSync, readFileSync } from "fs";
|
|
6
|
+
|
|
7
|
+
const cjsPath = resolve(__dirname, "bin/cli.js");
|
|
8
|
+
const esmPath = resolve(__dirname, "bin/cli.mjs");
|
|
9
|
+
|
|
10
|
+
const isESM = () => {
|
|
11
|
+
const packageJsonPath = resolve(process.cwd(), "package.json");
|
|
12
|
+
if (existsSync(packageJsonPath)) {
|
|
13
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
14
|
+
return packageJson.type === "module";
|
|
15
|
+
}
|
|
16
|
+
return false;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const scriptPath = isESM() ? esmPath : cjsPath;
|
|
20
|
+
|
|
21
|
+
if (!existsSync(scriptPath)) {
|
|
22
|
+
console.error(`Error: Script not found at ${scriptPath}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const result = spawnSync(
|
|
27
|
+
process.execPath,
|
|
28
|
+
[scriptPath, ...process.argv.slice(2)],
|
|
29
|
+
{
|
|
30
|
+
stdio: "inherit",
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
process.exit(result.status ?? 1);
|
package/src/bin/cli.ts
CHANGED
|
@@ -12,16 +12,10 @@ import { Migrator } from "../entity/migrator";
|
|
|
12
12
|
import { FixtureManager } from "../testing/fixture-manager";
|
|
13
13
|
import { tsicli } from "tsicli";
|
|
14
14
|
import { execSync } from "child_process";
|
|
15
|
-
import
|
|
16
|
-
existsSync,
|
|
17
|
-
mkdirSync,
|
|
18
|
-
readdirSync,
|
|
19
|
-
unlinkSync,
|
|
20
|
-
writeFileSync,
|
|
21
|
-
} from "fs";
|
|
15
|
+
import fs from "fs-extra";
|
|
22
16
|
import { Sonamu } from "../api";
|
|
23
17
|
import knex, { Knex } from "knex";
|
|
24
|
-
import
|
|
18
|
+
import inflection from "inflection";
|
|
25
19
|
import prettier from "prettier";
|
|
26
20
|
import { SMDManager } from "../smd/smd-manager";
|
|
27
21
|
import process from "process";
|
|
@@ -241,11 +235,11 @@ async function fixture_sync() {
|
|
|
241
235
|
|
|
242
236
|
async function stub_practice(name: string) {
|
|
243
237
|
const practiceDir = path.join(Sonamu.apiRootPath, "src", "practices");
|
|
244
|
-
const fileNames = readdirSync(practiceDir);
|
|
238
|
+
const fileNames = fs.readdirSync(practiceDir);
|
|
245
239
|
|
|
246
240
|
const maxSeqNo = (() => {
|
|
247
|
-
if (existsSync(practiceDir) === false) {
|
|
248
|
-
mkdirSync(practiceDir, { recursive: true });
|
|
241
|
+
if (fs.existsSync(practiceDir) === false) {
|
|
242
|
+
fs.mkdirSync(practiceDir, { recursive: true });
|
|
249
243
|
}
|
|
250
244
|
|
|
251
245
|
const filteredSeqs = fileNames
|
|
@@ -282,7 +276,7 @@ async function stub_practice(name: string) {
|
|
|
282
276
|
`await BaseModel.destroy();`,
|
|
283
277
|
`});`,
|
|
284
278
|
].join("\n");
|
|
285
|
-
writeFileSync(dstPath, code);
|
|
279
|
+
fs.writeFileSync(dstPath, code);
|
|
286
280
|
|
|
287
281
|
execSync(`code ${dstPath}`);
|
|
288
282
|
|
|
@@ -338,7 +332,7 @@ async function smd_migration() {
|
|
|
338
332
|
return Object.fromEntries(
|
|
339
333
|
Object.entries(enumLabels).map(([enumLabelName, enumLabel]) => {
|
|
340
334
|
const enumName =
|
|
341
|
-
entityId + camelize(enumLabelName.toLowerCase(), false);
|
|
335
|
+
entityId + inflection.camelize(enumLabelName.toLowerCase(), false);
|
|
342
336
|
return [
|
|
343
337
|
enumName,
|
|
344
338
|
Object.fromEntries(
|
|
@@ -373,7 +367,7 @@ async function smd_migration() {
|
|
|
373
367
|
const formatted = await prettier.format(JSON.stringify(entityJson), {
|
|
374
368
|
parser: "json",
|
|
375
369
|
});
|
|
376
|
-
writeFileSync(dstPath, formatted);
|
|
370
|
+
fs.writeFileSync(dstPath, formatted);
|
|
377
371
|
console.log(chalk.blue(`CREATED: ${dstPath}`));
|
|
378
372
|
|
|
379
373
|
// smd.ts, enums.ts, genereated.ts 삭제 (트랜스파일 된 js파일도 삭제)
|
|
@@ -421,11 +415,11 @@ async function smd_migration() {
|
|
|
421
415
|
srcGeneratedPath,
|
|
422
416
|
dstGeneratedPath,
|
|
423
417
|
].map((p) => {
|
|
424
|
-
if (existsSync(p) === false) {
|
|
418
|
+
if (fs.existsSync(p) === false) {
|
|
425
419
|
console.log(chalk.yellow(`NOT FOUND: ${p}`));
|
|
426
420
|
return;
|
|
427
421
|
}
|
|
428
|
-
unlinkSync(p);
|
|
422
|
+
fs.unlinkSync(p);
|
|
429
423
|
console.log(chalk.red(`DELETED: ${p}`));
|
|
430
424
|
});
|
|
431
425
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
2
|
import { Knex } from "knex";
|
|
3
|
-
import
|
|
3
|
+
import _ from "lodash";
|
|
4
4
|
import { attachOnDuplicateUpdate } from "./knex-plugins/knex-on-duplicate-update";
|
|
5
5
|
attachOnDuplicateUpdate();
|
|
6
6
|
import { DBPreset, DB } from "./db";
|
|
7
7
|
import { isCustomJoinClause, SubsetQuery } from "../types/types";
|
|
8
8
|
import { BaseListParams } from "../utils/model";
|
|
9
|
-
import
|
|
9
|
+
import inflection from "inflection";
|
|
10
10
|
import chalk from "chalk";
|
|
11
11
|
import { UpsertBuilder } from "./upsert-builder";
|
|
12
|
-
import
|
|
12
|
+
import SqlParser from "node-sql-parser";
|
|
13
13
|
import { getTableName, getTableNamesFromWhere } from "../utils/sql-parser";
|
|
14
14
|
|
|
15
15
|
export class BaseModelClass {
|
|
@@ -55,7 +55,7 @@ export class BaseModelClass {
|
|
|
55
55
|
selectField = unqKeyFields[0];
|
|
56
56
|
unqKeys = rows.map((row) => row[unqKeyFields[0]]);
|
|
57
57
|
}
|
|
58
|
-
const chunks = chunk(unqKeys, chunkSize);
|
|
58
|
+
const chunks = _.chunk(unqKeys, chunkSize);
|
|
59
59
|
|
|
60
60
|
let resultIds: number[] = [];
|
|
61
61
|
for (let chunk of chunks) {
|
|
@@ -114,7 +114,7 @@ export class BaseModelClass {
|
|
|
114
114
|
`${loader.manyJoin.toTable}.${loader.manyJoin.toCol}`
|
|
115
115
|
)
|
|
116
116
|
.whereIn(idColumn, fromIds)
|
|
117
|
-
.select(uniq([...loader.select, idColumn]));
|
|
117
|
+
.select(_.uniq([...loader.select, idColumn]));
|
|
118
118
|
|
|
119
119
|
// ManyToMany에서 OneJoin이 있는 경우
|
|
120
120
|
loader.oneJoins.map((join) => {
|
|
@@ -140,10 +140,10 @@ export class BaseModelClass {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// 불러온 row들을 참조ID 기준으로 분류 배치
|
|
143
|
-
const subRowGroups = groupBy(subRows, toCol);
|
|
143
|
+
const subRowGroups = _.groupBy(subRows, toCol);
|
|
144
144
|
rows = rows.map((row) => {
|
|
145
145
|
row[loader.as] = (subRowGroups[row[loader.manyJoin.idField]] ?? []).map(
|
|
146
|
-
(r) => omit(r, toCol)
|
|
146
|
+
(r) => _.omit(r, toCol)
|
|
147
147
|
);
|
|
148
148
|
return row;
|
|
149
149
|
});
|
|
@@ -155,7 +155,7 @@ export class BaseModelClass {
|
|
|
155
155
|
return rows.map((row: any) => {
|
|
156
156
|
// nullable relation인 경우 관련된 필드가 전부 null로 생성되는 것 방지하는 코드
|
|
157
157
|
const nestedKeys = Object.keys(row).filter((key) => key.includes("__"));
|
|
158
|
-
const groups = groupBy(nestedKeys, (key) => key.split("__")[0]);
|
|
158
|
+
const groups = _.groupBy(nestedKeys, (key) => key.split("__")[0]);
|
|
159
159
|
const nullKeys = Object.keys(groups).filter(
|
|
160
160
|
(key) =>
|
|
161
161
|
groups[key].length > 1 &&
|
|
@@ -164,7 +164,7 @@ export class BaseModelClass {
|
|
|
164
164
|
|
|
165
165
|
const hydrated = Object.keys(row).reduce((r, field) => {
|
|
166
166
|
if (!field.includes("__")) {
|
|
167
|
-
if (Array.isArray(row[field]) && isObject(row[field][0])) {
|
|
167
|
+
if (Array.isArray(row[field]) && _.isObject(row[field][0])) {
|
|
168
168
|
r[field] = this.hydrate(row[field]);
|
|
169
169
|
return r;
|
|
170
170
|
} else {
|
|
@@ -180,10 +180,10 @@ export class BaseModelClass {
|
|
|
180
180
|
.slice(1)
|
|
181
181
|
.map((part) => `[${part}]`)
|
|
182
182
|
.join("");
|
|
183
|
-
set(
|
|
183
|
+
_.set(
|
|
184
184
|
r,
|
|
185
185
|
objPath,
|
|
186
|
-
row[field] && Array.isArray(row[field]) && isObject(row[field][0])
|
|
186
|
+
row[field] && Array.isArray(row[field]) && _.isObject(row[field][0])
|
|
187
187
|
? this.hydrate(row[field])
|
|
188
188
|
: row[field]
|
|
189
189
|
);
|
|
@@ -227,7 +227,8 @@ export class BaseModelClass {
|
|
|
227
227
|
qb: Knex.QueryBuilder;
|
|
228
228
|
}> {
|
|
229
229
|
const db = _db ?? this.getDB(subset.startsWith("A") ? "w" : "r");
|
|
230
|
-
baseTable =
|
|
230
|
+
baseTable =
|
|
231
|
+
baseTable ?? inflection.pluralize(inflection.underscore(this.modelName));
|
|
231
232
|
const queryMode =
|
|
232
233
|
params.queryMode ?? (params.id !== undefined ? "list" : "both");
|
|
233
234
|
|
|
@@ -266,15 +267,17 @@ export class BaseModelClass {
|
|
|
266
267
|
}
|
|
267
268
|
|
|
268
269
|
const clonedQb = qb.clone().clear("order").clear("offset").clear("limit");
|
|
269
|
-
const parser = new Parser();
|
|
270
|
+
const parser = new SqlParser.Parser();
|
|
270
271
|
|
|
271
272
|
// optmizeCountQuery가 true인 경우 다른 clause에 영향을 주지 않는 모든 join을 제외함
|
|
272
273
|
if (optimizeCountQuery) {
|
|
273
274
|
const parsedQuery = parser.astify(clonedQb.toQuery());
|
|
274
275
|
const tables = getTableNamesFromWhere(parsedQuery);
|
|
275
276
|
// where절에 사용되는 테이블의 조인을 위해 사용되는 테이블
|
|
276
|
-
const needToJoin = uniq(
|
|
277
|
-
tables.flatMap((table) =>
|
|
277
|
+
const needToJoin = _.uniq(
|
|
278
|
+
tables.flatMap((table) =>
|
|
279
|
+
table.split("__").map((t) => inflection.pluralize(t))
|
|
280
|
+
)
|
|
278
281
|
);
|
|
279
282
|
applyJoinClause(
|
|
280
283
|
clonedQb,
|
package/src/database/db.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { v4 as uuidv4 } from "uuid";
|
|
2
|
-
import
|
|
2
|
+
import _ from "lodash";
|
|
3
3
|
import { Knex } from "knex";
|
|
4
4
|
import { EntityManager } from "../entity/entity-manager";
|
|
5
5
|
import { nonNullable } from "../utils/utils";
|
|
@@ -178,7 +178,7 @@ export class UpsertBuilder {
|
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
// 내부 참조 있는 경우 필터하여 분리
|
|
181
|
-
const groups = groupBy(table.rows, (row) =>
|
|
181
|
+
const groups = _.groupBy(table.rows, (row) =>
|
|
182
182
|
Object.entries(row).some(([, value]) => isRefField(value))
|
|
183
183
|
? "selfRef"
|
|
184
184
|
: "normal"
|
|
@@ -212,14 +212,14 @@ export class UpsertBuilder {
|
|
|
212
212
|
}
|
|
213
213
|
);
|
|
214
214
|
|
|
215
|
-
const extractFields = uniq(references).map(
|
|
215
|
+
const extractFields = _.uniq(references).map(
|
|
216
216
|
(reference) => reference.split(".")[1]
|
|
217
217
|
);
|
|
218
218
|
|
|
219
219
|
// UUID 기준으로 id 추출
|
|
220
220
|
const uuids = table.rows.map((row) => row.uuid);
|
|
221
221
|
const upsertedRows = await wdb(tableName)
|
|
222
|
-
.select(uniq(["uuid", "id", ...extractFields]))
|
|
222
|
+
.select(_.uniq(["uuid", "id", ...extractFields]))
|
|
223
223
|
.whereIn("uuid", uuids);
|
|
224
224
|
const uuidMap = new Map<string, any>(
|
|
225
225
|
upsertedRows.map((row: any) => [row.uuid, row])
|
|
@@ -263,7 +263,7 @@ export class UpsertBuilder {
|
|
|
263
263
|
where?: string;
|
|
264
264
|
}
|
|
265
265
|
): Promise<void> {
|
|
266
|
-
options = defaults(options, {
|
|
266
|
+
options = _.defaults(options, {
|
|
267
267
|
chunkSize: 500,
|
|
268
268
|
where: "id",
|
|
269
269
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import glob from "glob";
|
|
3
|
+
import inflection from "inflection";
|
|
4
4
|
import _ from "lodash";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { Entity } from "./entity";
|
|
7
7
|
import { EntityJson } from "../types/types";
|
|
8
8
|
import { Sonamu } from "../api/sonamu";
|
|
9
|
-
import
|
|
9
|
+
import fs from "fs-extra";
|
|
10
10
|
|
|
11
11
|
export type EntityNamesRecord = Record<
|
|
12
12
|
| "fs"
|
|
@@ -41,10 +41,10 @@ class EntityManagerClass {
|
|
|
41
41
|
!doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));
|
|
42
42
|
|
|
43
43
|
return new Promise((resolve) => {
|
|
44
|
-
glob(path.resolve(pathPattern!), (_err, files) => {
|
|
44
|
+
glob.glob(path.resolve(pathPattern!), (_err, files) => {
|
|
45
45
|
Promise.all(
|
|
46
46
|
files.map(async (file) => {
|
|
47
|
-
this.register(JSON.parse(readFileSync(file).toString()));
|
|
47
|
+
this.register(JSON.parse(fs.readFileSync(file).toString()));
|
|
48
48
|
})
|
|
49
49
|
).then(() => {
|
|
50
50
|
resolve("ok");
|
|
@@ -139,19 +139,21 @@ class EntityManagerClass {
|
|
|
139
139
|
getNamesFromId(entityId: string): EntityNamesRecord {
|
|
140
140
|
// entityId가 단복수 동형 단어인 경우 List 붙여서 생성
|
|
141
141
|
const pluralized =
|
|
142
|
-
pluralize(entityId) === entityId
|
|
142
|
+
inflection.pluralize(entityId) === entityId
|
|
143
143
|
? `${entityId}List`
|
|
144
|
-
: pluralize(entityId);
|
|
144
|
+
: inflection.pluralize(entityId);
|
|
145
145
|
|
|
146
146
|
return {
|
|
147
|
-
fs: dasherize(underscore(entityId)).toLowerCase(),
|
|
148
|
-
fsPlural:
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
fs: inflection.dasherize(inflection.underscore(entityId)).toLowerCase(),
|
|
148
|
+
fsPlural: inflection
|
|
149
|
+
.dasherize(inflection.underscore(pluralized))
|
|
150
|
+
.toLowerCase(),
|
|
151
|
+
camel: inflection.camelize(entityId, true),
|
|
152
|
+
camelPlural: inflection.camelize(pluralized, true),
|
|
151
153
|
capital: entityId,
|
|
152
154
|
capitalPlural: pluralized,
|
|
153
155
|
upper: entityId.toUpperCase(),
|
|
154
|
-
constant: underscore(entityId).toUpperCase(),
|
|
156
|
+
constant: inflection.underscore(entityId).toUpperCase(),
|
|
155
157
|
};
|
|
156
158
|
}
|
|
157
159
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import inflection from "inflection";
|
|
2
2
|
import {
|
|
3
3
|
BelongsToOneRelationProp,
|
|
4
4
|
BigIntegerProp,
|
|
@@ -208,7 +208,7 @@ function enums(
|
|
|
208
208
|
return {
|
|
209
209
|
name,
|
|
210
210
|
type: "enum",
|
|
211
|
-
id: option.id ?? `$Model${camelize(name)}`,
|
|
211
|
+
id: option.id ?? `$Model${inflection.camelize(name)}`,
|
|
212
212
|
...option,
|
|
213
213
|
};
|
|
214
214
|
}
|
package/src/entity/entity.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _ from "lodash";
|
|
2
2
|
import { EntityManager as EntityManager } from "./entity-manager";
|
|
3
|
-
import { dasherize, pluralize, underscore } from "inflection";
|
|
4
3
|
import {
|
|
5
4
|
EntityProp,
|
|
6
5
|
RelationProp,
|
|
@@ -20,7 +19,7 @@ import {
|
|
|
20
19
|
} from "../types/types";
|
|
21
20
|
import inflection from "inflection";
|
|
22
21
|
import path from "path";
|
|
23
|
-
import
|
|
22
|
+
import fs from "fs-extra";
|
|
24
23
|
import { z } from "zod";
|
|
25
24
|
import { Sonamu } from "../api/sonamu";
|
|
26
25
|
import prettier from "prettier";
|
|
@@ -73,7 +72,7 @@ export class Entity {
|
|
|
73
72
|
this.id = id;
|
|
74
73
|
this.parentId = parentId;
|
|
75
74
|
this.title = title ?? this.id;
|
|
76
|
-
this.table = table ?? underscore(pluralize(id));
|
|
75
|
+
this.table = table ?? inflection.underscore(inflection.pluralize(id));
|
|
77
76
|
|
|
78
77
|
// props
|
|
79
78
|
if (props) {
|
|
@@ -128,8 +127,10 @@ export class Entity {
|
|
|
128
127
|
|
|
129
128
|
// names
|
|
130
129
|
this.names = {
|
|
131
|
-
parentFs:
|
|
132
|
-
|
|
130
|
+
parentFs: inflection
|
|
131
|
+
.dasherize(inflection.underscore(parentId ?? id))
|
|
132
|
+
.toLowerCase(),
|
|
133
|
+
fs: inflection.dasherize(inflection.underscore(id)).toLowerCase(),
|
|
133
134
|
module: id,
|
|
134
135
|
};
|
|
135
136
|
|
|
@@ -158,7 +159,7 @@ export class Entity {
|
|
|
158
159
|
prefix = prefix.replace(/\./g, "__");
|
|
159
160
|
|
|
160
161
|
// 서브셋을 1뎁스만 분리하여 그룹핑
|
|
161
|
-
const subsetGroup = groupBy(fields, (field) => {
|
|
162
|
+
const subsetGroup = _.groupBy(fields, (field) => {
|
|
162
163
|
if (field.includes(".")) {
|
|
163
164
|
const [rel] = field.split(".");
|
|
164
165
|
return rel;
|
|
@@ -271,7 +272,7 @@ export class Entity {
|
|
|
271
272
|
to = `${joinAs}.id`;
|
|
272
273
|
} else {
|
|
273
274
|
from = `${fromTable}.id`;
|
|
274
|
-
to = `${joinAs}.${underscore(
|
|
275
|
+
to = `${joinAs}.${inflection.underscore(
|
|
275
276
|
this.names.fs.replace(/\-/g, "_")
|
|
276
277
|
)}_id`;
|
|
277
278
|
}
|
|
@@ -302,6 +303,7 @@ export class Entity {
|
|
|
302
303
|
manyJoin: loader.manyJoin,
|
|
303
304
|
oneJoins: loader.oneJoins,
|
|
304
305
|
select: loader.select,
|
|
306
|
+
loaders: loader.loaders,
|
|
305
307
|
};
|
|
306
308
|
});
|
|
307
309
|
|
|
@@ -575,7 +577,7 @@ export class Entity {
|
|
|
575
577
|
`dist/application/${typesModulePath}.js`
|
|
576
578
|
);
|
|
577
579
|
|
|
578
|
-
if (existsSync(typesFileDistPath)) {
|
|
580
|
+
if (fs.existsSync(typesFileDistPath)) {
|
|
579
581
|
const importPath = path.relative(__dirname, typesFileDistPath);
|
|
580
582
|
import(importPath).then((t) => {
|
|
581
583
|
this.types = Object.keys(t).reduce((result, key) => {
|
|
@@ -629,7 +631,7 @@ export class Entity {
|
|
|
629
631
|
`src/application/${this.names.parentFs}/${this.names.fs}.entity.json`
|
|
630
632
|
);
|
|
631
633
|
const json = this.toJson();
|
|
632
|
-
writeFileSync(
|
|
634
|
+
fs.writeFileSync(
|
|
633
635
|
jsonPath,
|
|
634
636
|
await prettier.format(JSON.stringify(json), {
|
|
635
637
|
parser: "json",
|
|
@@ -650,7 +652,7 @@ export class Entity {
|
|
|
650
652
|
|
|
651
653
|
const subsets = _subsets ?? this.subsets;
|
|
652
654
|
const subsetKeys = Object.keys(subsets);
|
|
653
|
-
const allFields = uniq(subsetKeys.map((key) => subsets[key]).flat());
|
|
655
|
+
const allFields = _.uniq(subsetKeys.map((key) => subsets[key]).flat());
|
|
654
656
|
|
|
655
657
|
return this.props.map((prop) => {
|
|
656
658
|
if (
|