sonamu 0.0.8 → 0.0.10
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/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +1 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/init.d.ts +35 -5
- package/dist/api/init.d.ts.map +1 -1
- package/dist/api/init.js +142 -79
- package/dist/api/init.js.map +1 -1
- package/dist/api/sonamu.d.ts +42 -0
- package/dist/api/sonamu.d.ts.map +1 -0
- package/dist/api/sonamu.js +175 -0
- package/dist/api/sonamu.js.map +1 -0
- package/dist/bin/cli.js +6 -21
- package/dist/bin/cli.js.map +1 -1
- package/dist/database/db.d.ts +1 -3
- package/dist/database/db.d.ts.map +1 -1
- package/dist/database/db.js +12 -23
- package/dist/database/db.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/smd/migrator.d.ts +0 -5
- package/dist/smd/migrator.d.ts.map +1 -1
- package/dist/smd/migrator.js +18 -19
- package/dist/smd/migrator.js.map +1 -1
- package/dist/smd/smd-manager.d.ts.map +1 -1
- package/dist/smd/smd-manager.js +2 -3
- package/dist/smd/smd-manager.js.map +1 -1
- package/dist/smd/smd.d.ts.map +1 -1
- package/dist/smd/smd.js +3 -4
- package/dist/smd/smd.js.map +1 -1
- package/dist/syncer/syncer.d.ts +8 -12
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +46 -43
- package/dist/syncer/syncer.js.map +1 -1
- package/dist/templates/generated_http.template.js +2 -2
- package/dist/templates/generated_http.template.js.map +1 -1
- package/dist/templates/service.template.d.ts +1 -1
- package/dist/templates/service.template.d.ts.map +1 -1
- package/dist/templates/service.template.js +3 -2
- package/dist/templates/service.template.js.map +1 -1
- package/dist/templates/view_form.template.d.ts +2 -2
- package/dist/templates/view_list.template.d.ts +2 -2
- package/dist/testing/fixture-manager.d.ts +6 -7
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +35 -42
- package/dist/testing/fixture-manager.js.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 +10 -3
- package/dist/utils/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/api/index.ts +1 -1
- package/src/api/sonamu.ts +212 -0
- package/src/bin/cli.ts +6 -26
- package/src/database/db.ts +15 -27
- package/src/index.ts +1 -1
- package/src/smd/migrator.ts +18 -31
- package/src/smd/smd-manager.ts +3 -4
- package/src/smd/smd.ts +7 -8
- package/src/syncer/syncer.ts +58 -68
- package/src/templates/generated_http.template.ts +2 -2
- package/src/templates/service.template.ts +6 -5
- package/src/testing/fixture-manager.ts +44 -54
- package/src/utils/utils.ts +6 -1
- package/src/api/init.ts +0 -129
package/src/bin/cli.ts
CHANGED
|
@@ -7,27 +7,19 @@ dotenv.config();
|
|
|
7
7
|
|
|
8
8
|
import path from "path";
|
|
9
9
|
import { BaseModel } from "../database/base-model";
|
|
10
|
-
import { DB } from "../database/db";
|
|
11
10
|
import { SMDManager } from "../smd/smd-manager";
|
|
12
11
|
import { Migrator } from "../smd/migrator";
|
|
13
|
-
import { Syncer } from "../syncer/syncer";
|
|
14
12
|
import { FixtureManager } from "../testing/fixture-manager";
|
|
15
13
|
import { tsicli } from "tsicli";
|
|
16
14
|
import { execSync } from "child_process";
|
|
17
15
|
import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
|
|
18
|
-
import {
|
|
16
|
+
import { Sonamu } from "../api";
|
|
19
17
|
|
|
20
18
|
let migrator: Migrator;
|
|
21
19
|
let fixtureManager: FixtureManager;
|
|
22
20
|
|
|
23
21
|
async function bootstrap() {
|
|
24
|
-
|
|
25
|
-
const appRootPath = await findAppRootPath();
|
|
26
|
-
Syncer.getInstance({
|
|
27
|
-
appRootPath,
|
|
28
|
-
});
|
|
29
|
-
await DB.readKnexfile(appRootPath);
|
|
30
|
-
await SMDManager.autoload();
|
|
22
|
+
await Sonamu.init();
|
|
31
23
|
|
|
32
24
|
await tsicli(process.argv, {
|
|
33
25
|
types: {
|
|
@@ -89,8 +81,6 @@ bootstrap().finally(async () => {
|
|
|
89
81
|
async function setupMigrator() {
|
|
90
82
|
// migrator
|
|
91
83
|
migrator = new Migrator({
|
|
92
|
-
appRootPath: Syncer.getInstance().config.appRootPath,
|
|
93
|
-
knexfile: DB.getKnexfile(),
|
|
94
84
|
mode: "dev",
|
|
95
85
|
});
|
|
96
86
|
}
|
|
@@ -138,14 +128,7 @@ async function fixture_sync() {
|
|
|
138
128
|
}
|
|
139
129
|
|
|
140
130
|
async function stub_practice(name: string) {
|
|
141
|
-
|
|
142
|
-
return;
|
|
143
|
-
const practiceDir = path.join(
|
|
144
|
-
Syncer.getInstance().config.appRootPath,
|
|
145
|
-
"api",
|
|
146
|
-
"src",
|
|
147
|
-
"practices"
|
|
148
|
-
);
|
|
131
|
+
const practiceDir = path.join(Sonamu.apiRootPath, "src", "practices");
|
|
149
132
|
const fileNames = readdirSync(practiceDir);
|
|
150
133
|
|
|
151
134
|
const maxSeqNo = (() => {
|
|
@@ -200,22 +183,19 @@ async function stub_practice(name: string) {
|
|
|
200
183
|
}
|
|
201
184
|
|
|
202
185
|
async function stub_smd(name: string) {
|
|
203
|
-
|
|
204
|
-
await syncer.generateTemplate("smd", {
|
|
186
|
+
await Sonamu.syncer.generateTemplate("smd", {
|
|
205
187
|
smdId: name,
|
|
206
188
|
});
|
|
207
189
|
}
|
|
208
190
|
|
|
209
191
|
async function scaffold_model(smdId: string) {
|
|
210
|
-
|
|
211
|
-
await syncer.generateTemplate("model", {
|
|
192
|
+
await Sonamu.syncer.generateTemplate("model", {
|
|
212
193
|
smdId,
|
|
213
194
|
});
|
|
214
195
|
}
|
|
215
196
|
|
|
216
197
|
async function scaffold_model_test(smdId: string) {
|
|
217
|
-
|
|
218
|
-
await syncer.generateTemplate("model_test", {
|
|
198
|
+
await Sonamu.syncer.generateTemplate("model_test", {
|
|
219
199
|
smdId,
|
|
220
200
|
});
|
|
221
201
|
}
|
package/src/database/db.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type DBPreset = "w" | "r";
|
|
2
2
|
import knex, { Knex } from "knex";
|
|
3
3
|
import path from "path";
|
|
4
|
+
import { Sonamu } from "../api";
|
|
4
5
|
import { ServiceUnavailableException } from "../exceptions/so-exceptions";
|
|
5
|
-
import { findAppRootPath } from "../utils/utils";
|
|
6
6
|
|
|
7
7
|
export type SonamuDBConfig = {
|
|
8
8
|
development_master: Knex.Config;
|
|
@@ -17,36 +17,24 @@ export type SonamuDBConfig = {
|
|
|
17
17
|
class DBClass {
|
|
18
18
|
private wdb?: Knex;
|
|
19
19
|
private rdb?: Knex;
|
|
20
|
-
private knexfile?: SonamuDBConfig;
|
|
21
20
|
|
|
22
|
-
async readKnexfile(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const appRootPath = _appRootPath ?? (await findAppRootPath());
|
|
28
|
-
const configPath: string = path.join(appRootPath, "/api/dist/configs/db");
|
|
21
|
+
async readKnexfile(): Promise<SonamuDBConfig> {
|
|
22
|
+
const dbConfigPath: string = path.join(
|
|
23
|
+
Sonamu.apiRootPath,
|
|
24
|
+
"/dist/configs/db"
|
|
25
|
+
);
|
|
29
26
|
try {
|
|
30
|
-
const knexfileModule = await import(
|
|
31
|
-
|
|
32
|
-
return this.knexfile;
|
|
27
|
+
const knexfileModule = await import(dbConfigPath);
|
|
28
|
+
return knexfileModule.default as SonamuDBConfig;
|
|
33
29
|
} catch {}
|
|
34
30
|
|
|
35
31
|
throw new ServiceUnavailableException(
|
|
36
|
-
`DB설정 파일을 찾을 수 없습니다. ${
|
|
32
|
+
`DB설정 파일을 찾을 수 없습니다. ${dbConfigPath}`
|
|
37
33
|
);
|
|
38
34
|
}
|
|
39
35
|
|
|
40
|
-
getKnexfile(): SonamuDBConfig {
|
|
41
|
-
if (this.knexfile) {
|
|
42
|
-
return this.knexfile;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
throw new ServiceUnavailableException("DB설정이 로드되지 않았습니다.");
|
|
46
|
-
}
|
|
47
|
-
|
|
48
36
|
getDB(which: DBPreset): Knex {
|
|
49
|
-
const
|
|
37
|
+
const dbConfig = Sonamu.dbConfig;
|
|
50
38
|
|
|
51
39
|
const instanceName = which === "w" ? "wdb" : "rdb";
|
|
52
40
|
|
|
@@ -57,17 +45,17 @@ class DBClass {
|
|
|
57
45
|
case "staging":
|
|
58
46
|
config =
|
|
59
47
|
which === "w"
|
|
60
|
-
?
|
|
61
|
-
:
|
|
48
|
+
? dbConfig["development_master"]
|
|
49
|
+
: dbConfig["development_slave"] ?? dbConfig["development_master"];
|
|
62
50
|
break;
|
|
63
51
|
case "production":
|
|
64
52
|
config =
|
|
65
53
|
which === "w"
|
|
66
|
-
?
|
|
67
|
-
:
|
|
54
|
+
? dbConfig["production_master"]
|
|
55
|
+
: dbConfig["production_slave"] ?? dbConfig["production_master"];
|
|
68
56
|
break;
|
|
69
57
|
case "test":
|
|
70
|
-
config =
|
|
58
|
+
config = dbConfig["test"];
|
|
71
59
|
break;
|
|
72
60
|
default:
|
|
73
61
|
throw new Error(
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./api/code-converters";
|
|
2
2
|
export * from "./api/context";
|
|
3
3
|
export * from "./api/decorators";
|
|
4
|
-
export * from "./api/
|
|
4
|
+
export * from "./api/sonamu";
|
|
5
5
|
export * from "./database/base-model";
|
|
6
6
|
export * from "./database/db";
|
|
7
7
|
export * from "./database/upsert-builder";
|
package/src/smd/migrator.ts
CHANGED
|
@@ -49,17 +49,13 @@ import {
|
|
|
49
49
|
import { propIf } from "../utils/lodash-able";
|
|
50
50
|
import { SMDManager } from "./smd-manager";
|
|
51
51
|
import { SMD } from "./smd";
|
|
52
|
-
import {
|
|
52
|
+
import { Sonamu } from "../api";
|
|
53
53
|
|
|
54
54
|
type MigratorMode = "dev" | "deploy";
|
|
55
55
|
export type MigratorOptions = {
|
|
56
|
-
appRootPath: string;
|
|
57
|
-
knexfile: SonamuDBConfig;
|
|
58
56
|
readonly mode: MigratorMode;
|
|
59
57
|
};
|
|
60
58
|
export class Migrator {
|
|
61
|
-
appRootPath: string;
|
|
62
|
-
knexfile: SonamuDBConfig;
|
|
63
59
|
readonly mode: MigratorMode;
|
|
64
60
|
|
|
65
61
|
targets: {
|
|
@@ -70,23 +66,21 @@ export class Migrator {
|
|
|
70
66
|
};
|
|
71
67
|
|
|
72
68
|
constructor(options: MigratorOptions) {
|
|
73
|
-
this.appRootPath = options.appRootPath;
|
|
74
|
-
this.knexfile = options.knexfile;
|
|
75
69
|
this.mode = options.mode;
|
|
70
|
+
const { dbConfig } = Sonamu;
|
|
76
71
|
|
|
77
72
|
if (this.mode === "dev") {
|
|
78
|
-
const devDB = knex(
|
|
79
|
-
const testDB = knex(
|
|
80
|
-
const fixtureLocalDB = knex(
|
|
73
|
+
const devDB = knex(dbConfig.development_master);
|
|
74
|
+
const testDB = knex(dbConfig.test);
|
|
75
|
+
const fixtureLocalDB = knex(dbConfig.fixture_local);
|
|
81
76
|
|
|
82
77
|
const applyDBs = [devDB, testDB, fixtureLocalDB];
|
|
83
78
|
if (
|
|
84
|
-
(
|
|
79
|
+
(dbConfig.fixture_local.connection as Knex.MySql2ConnectionConfig)
|
|
85
80
|
.host !==
|
|
86
|
-
(
|
|
87
|
-
.host
|
|
81
|
+
(dbConfig.fixture_remote.connection as Knex.MySql2ConnectionConfig).host
|
|
88
82
|
) {
|
|
89
|
-
const fixtureRemoteDB = knex(
|
|
83
|
+
const fixtureRemoteDB = knex(dbConfig.fixture_remote);
|
|
90
84
|
applyDBs.push(fixtureRemoteDB);
|
|
91
85
|
}
|
|
92
86
|
|
|
@@ -97,8 +91,8 @@ export class Migrator {
|
|
|
97
91
|
apply: applyDBs,
|
|
98
92
|
};
|
|
99
93
|
} else if (this.mode === "deploy") {
|
|
100
|
-
const productionDB = knex(
|
|
101
|
-
const testDB = knex(
|
|
94
|
+
const productionDB = knex(Sonamu.dbConfig.production_master);
|
|
95
|
+
const testDB = knex(Sonamu.dbConfig.test);
|
|
102
96
|
|
|
103
97
|
this.targets = {
|
|
104
98
|
pending: productionDB,
|
|
@@ -118,7 +112,7 @@ export class Migrator {
|
|
|
118
112
|
directory: string;
|
|
119
113
|
}[]
|
|
120
114
|
];
|
|
121
|
-
const migrationsDir = `${
|
|
115
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
122
116
|
const delList = pendingList.map((df) => {
|
|
123
117
|
return path.join(migrationsDir, df.file).replace(".js", ".ts");
|
|
124
118
|
});
|
|
@@ -197,7 +191,7 @@ export class Migrator {
|
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
// 실제 코드 생성
|
|
200
|
-
const migrationsDir = `${
|
|
194
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
201
195
|
codes
|
|
202
196
|
.filter((code) => code.formatted)
|
|
203
197
|
.map((code, index) => {
|
|
@@ -226,8 +220,7 @@ export class Migrator {
|
|
|
226
220
|
const files = (["src", "dist"] as const).reduce(
|
|
227
221
|
(r, which) => {
|
|
228
222
|
const migrationPath = path.join(
|
|
229
|
-
|
|
230
|
-
"api",
|
|
223
|
+
Sonamu.apiRootPath,
|
|
231
224
|
which,
|
|
232
225
|
"migrations"
|
|
233
226
|
);
|
|
@@ -281,13 +274,7 @@ export class Migrator {
|
|
|
281
274
|
}
|
|
282
275
|
|
|
283
276
|
const filesToRm = diffOnDist.map((filename) => {
|
|
284
|
-
return path.join(
|
|
285
|
-
this.appRootPath,
|
|
286
|
-
"api",
|
|
287
|
-
"dist",
|
|
288
|
-
"migrations",
|
|
289
|
-
filename
|
|
290
|
-
);
|
|
277
|
+
return path.join(Sonamu.apiRootPath, "dist", "migrations", filename);
|
|
291
278
|
});
|
|
292
279
|
filesToRm.map((filePath) => {
|
|
293
280
|
unlinkSync(filePath);
|
|
@@ -298,8 +285,8 @@ export class Migrator {
|
|
|
298
285
|
|
|
299
286
|
async runShadowTest(): Promise<boolean> {
|
|
300
287
|
// ShadowDB 생성 후 테스트 진행
|
|
301
|
-
const tdb = knex(
|
|
302
|
-
const tdbConn =
|
|
288
|
+
const tdb = knex(Sonamu.dbConfig.test);
|
|
289
|
+
const tdbConn = Sonamu.dbConfig.test.connection as Knex.ConnectionConfig;
|
|
303
290
|
const shadowDatabase = tdbConn.database + "__migration_shadow";
|
|
304
291
|
const tmpSqlPath = `/tmp/${shadowDatabase}.sql`;
|
|
305
292
|
|
|
@@ -330,7 +317,7 @@ export class Migrator {
|
|
|
330
317
|
|
|
331
318
|
// shadow db 테스트 진행
|
|
332
319
|
const sdb = knex({
|
|
333
|
-
...
|
|
320
|
+
...Sonamu.dbConfig.test,
|
|
334
321
|
connection: {
|
|
335
322
|
...tdbConn,
|
|
336
323
|
database: shadowDatabase,
|
|
@@ -378,7 +365,7 @@ export class Migrator {
|
|
|
378
365
|
console.log({ rollbackAllResult });
|
|
379
366
|
console.timeEnd(chalk.red("rollback-all:"));
|
|
380
367
|
|
|
381
|
-
const migrationsDir = `${
|
|
368
|
+
const migrationsDir = `${Sonamu.apiRootPath}/src/migrations`;
|
|
382
369
|
console.time(chalk.red("delete migration files"));
|
|
383
370
|
execSync(`rm -f ${migrationsDir}/*`);
|
|
384
371
|
execSync(`rm -f ${migrationsDir.replace("/src/", "/dist/")}/*`);
|
package/src/smd/smd-manager.ts
CHANGED
|
@@ -5,7 +5,7 @@ import _ from "lodash";
|
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { SMD } from "./smd";
|
|
7
7
|
import { SMDInput } from "../types/types";
|
|
8
|
-
import {
|
|
8
|
+
import { Sonamu } from "../api/sonamu";
|
|
9
9
|
|
|
10
10
|
export type SMDNamesRecord = Record<
|
|
11
11
|
| "fs"
|
|
@@ -33,10 +33,9 @@ class SMDManagerClass {
|
|
|
33
33
|
if (this.isAutoloaded) {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
-
const appRootPath = await findAppRootPath();
|
|
37
36
|
const pathPattern = path.join(
|
|
38
|
-
|
|
39
|
-
"/
|
|
37
|
+
Sonamu.apiRootPath,
|
|
38
|
+
"/dist/application/**/*.smd.js"
|
|
40
39
|
);
|
|
41
40
|
!doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));
|
|
42
41
|
|
package/src/smd/smd.ts
CHANGED
|
@@ -21,7 +21,7 @@ import path from "path";
|
|
|
21
21
|
import { existsSync } from "fs";
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
import { EnumsLabelKo } from "../types/types";
|
|
24
|
-
import {
|
|
24
|
+
import { Sonamu } from "../api/sonamu";
|
|
25
25
|
|
|
26
26
|
export class SMD {
|
|
27
27
|
id: string;
|
|
@@ -437,7 +437,6 @@ export class SMD {
|
|
|
437
437
|
|
|
438
438
|
registerModulePaths() {
|
|
439
439
|
const basePath = `${this.names.fs}`;
|
|
440
|
-
const appRootPath = Syncer.getInstance().config.appRootPath;
|
|
441
440
|
|
|
442
441
|
// base-scheme
|
|
443
442
|
SMDManager.setModulePath(
|
|
@@ -465,9 +464,9 @@ export class SMD {
|
|
|
465
464
|
|
|
466
465
|
// types
|
|
467
466
|
const typesModulePath = `${basePath}/${this.names.fs}.types`;
|
|
468
|
-
const typesFileDistPath = path.
|
|
469
|
-
|
|
470
|
-
`
|
|
467
|
+
const typesFileDistPath = path.join(
|
|
468
|
+
Sonamu.apiRootPath,
|
|
469
|
+
`dist/application/${typesModulePath}.js`
|
|
471
470
|
);
|
|
472
471
|
|
|
473
472
|
if (existsSync(typesFileDistPath)) {
|
|
@@ -485,9 +484,9 @@ export class SMD {
|
|
|
485
484
|
|
|
486
485
|
// enums
|
|
487
486
|
const enumsModulePath = `${basePath}/${this.names.fs}.enums`;
|
|
488
|
-
const enumsFileDistPath = path.
|
|
489
|
-
|
|
490
|
-
|
|
487
|
+
const enumsFileDistPath = path.join(
|
|
488
|
+
Sonamu.apiRootPath,
|
|
489
|
+
`/dist/application/${enumsModulePath}.js`
|
|
491
490
|
);
|
|
492
491
|
if (existsSync(enumsFileDistPath)) {
|
|
493
492
|
const importPath = path.relative(__dirname, enumsFileDistPath);
|
package/src/syncer/syncer.ts
CHANGED
|
@@ -82,12 +82,8 @@ import { Template__view_enums_buttonset } from "../templates/view_enums_buttonse
|
|
|
82
82
|
import { Template__view_search_input } from "../templates/view_search_input.template";
|
|
83
83
|
import { Template__view_list_columns } from "../templates/view_list_columns.template";
|
|
84
84
|
import { Template__generated_http } from "../templates/generated_http.template";
|
|
85
|
+
import { Sonamu } from "../api/sonamu";
|
|
85
86
|
|
|
86
|
-
type SyncerConfig = {
|
|
87
|
-
appRootPath: string;
|
|
88
|
-
checksumsPath: string;
|
|
89
|
-
targets: string[];
|
|
90
|
-
};
|
|
91
87
|
type FileType = "model" | "types" | "enums" | "smd" | "generated";
|
|
92
88
|
type GlobPattern = {
|
|
93
89
|
[key in FileType]: string;
|
|
@@ -112,15 +108,6 @@ export type RenderedTemplate = {
|
|
|
112
108
|
};
|
|
113
109
|
|
|
114
110
|
export class Syncer {
|
|
115
|
-
private static instance: Syncer;
|
|
116
|
-
public static getInstance(config?: Partial<SyncerConfig>) {
|
|
117
|
-
if (this.instance && config !== undefined) {
|
|
118
|
-
throw new Error("Syncer has already configured.");
|
|
119
|
-
}
|
|
120
|
-
return this.instance ?? (this.instance = new this(config));
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
config: SyncerConfig;
|
|
124
111
|
apis: {
|
|
125
112
|
typeParameters: ApiParamType.TypeParam[];
|
|
126
113
|
parameters: ApiParam[];
|
|
@@ -131,22 +118,19 @@ export class Syncer {
|
|
|
131
118
|
options: ApiDecoratorOptions;
|
|
132
119
|
}[] = [];
|
|
133
120
|
types: { [typeName: string]: z.ZodObject<any> } = {};
|
|
121
|
+
models: { [modelName: string]: unknown } = {};
|
|
134
122
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
config?.appRootPath ?? path.resolve(__dirname, "../../");
|
|
138
|
-
this.config = {
|
|
139
|
-
appRootPath,
|
|
140
|
-
checksumsPath: `${appRootPath}/api/.tf-checksum`,
|
|
141
|
-
targets: ["web"],
|
|
142
|
-
...config,
|
|
143
|
-
};
|
|
123
|
+
get checksumsPath(): string {
|
|
124
|
+
return path.join(Sonamu.apiRootPath, "/.tf-checksum");
|
|
144
125
|
}
|
|
126
|
+
public constructor() {}
|
|
145
127
|
|
|
146
128
|
async sync(): Promise<void> {
|
|
129
|
+
const { targets } = Sonamu.config.sync;
|
|
130
|
+
|
|
147
131
|
// 트리거와 무관하게 shared 분배
|
|
148
132
|
await Promise.all(
|
|
149
|
-
|
|
133
|
+
targets.map(async (target) => {
|
|
150
134
|
const srcCodePath = path
|
|
151
135
|
.join(__dirname, `../shared/${target}.shared.ts.txt`)
|
|
152
136
|
.replace("/dist/", "/src/");
|
|
@@ -155,7 +139,7 @@ export class Syncer {
|
|
|
155
139
|
}
|
|
156
140
|
|
|
157
141
|
const dstCodePath = path.join(
|
|
158
|
-
|
|
142
|
+
Sonamu.appRootPath,
|
|
159
143
|
target,
|
|
160
144
|
"src/services/sonamu.shared.ts"
|
|
161
145
|
);
|
|
@@ -233,10 +217,8 @@ export class Syncer {
|
|
|
233
217
|
// 트리거: model
|
|
234
218
|
if (diffTypes.includes("model")) {
|
|
235
219
|
const smdIds = this.getSMDIdFromPath(diffGroups["model"]);
|
|
236
|
-
|
|
237
220
|
console.log("// 액션: 서비스 생성");
|
|
238
221
|
await this.actionGenerateServices(smdIds);
|
|
239
|
-
|
|
240
222
|
console.log("// 액션: HTTP파일 생성");
|
|
241
223
|
await this.actionGenerateHttps(smdIds);
|
|
242
224
|
}
|
|
@@ -328,18 +310,26 @@ export class Syncer {
|
|
|
328
310
|
}
|
|
329
311
|
|
|
330
312
|
async actionSyncFilesToTargets(tsPaths: string[]): Promise<string[]> {
|
|
313
|
+
const { targets } = Sonamu.config.sync;
|
|
314
|
+
const { dir: apiDir } = Sonamu.config.api;
|
|
315
|
+
const { appRootPath } = Sonamu;
|
|
316
|
+
|
|
331
317
|
return (
|
|
332
318
|
await Promise.all(
|
|
333
|
-
|
|
319
|
+
targets.map(async (target) =>
|
|
334
320
|
Promise.all(
|
|
335
321
|
tsPaths.map(async (src) => {
|
|
336
322
|
const dst = src
|
|
337
|
-
.replace(
|
|
323
|
+
.replace(`/${apiDir}/`, `/${target}/`)
|
|
338
324
|
.replace("/application/", "/services/");
|
|
339
325
|
const dir = dirname(dst);
|
|
340
326
|
if (!existsSync(dir)) {
|
|
341
327
|
mkdirSync(dir, { recursive: true });
|
|
342
328
|
}
|
|
329
|
+
console.log(
|
|
330
|
+
"COPIED ",
|
|
331
|
+
chalk.blue(dst.replace(appRootPath + "/", ""))
|
|
332
|
+
);
|
|
343
333
|
await this.copyFileWithReplaceCoreToShared(src, dst);
|
|
344
334
|
return dst;
|
|
345
335
|
})
|
|
@@ -352,13 +342,12 @@ export class Syncer {
|
|
|
352
342
|
async getCurrentChecksums(): Promise<PathAndChecksum[]> {
|
|
353
343
|
const PatternGroup: GlobPattern = {
|
|
354
344
|
/* TS 체크 */
|
|
355
|
-
types:
|
|
356
|
-
enums:
|
|
357
|
-
generated:
|
|
358
|
-
this.config.appRootPath + "/api/src/application/**/*.generated.ts",
|
|
345
|
+
types: Sonamu.apiRootPath + "/src/application/**/*.types.ts",
|
|
346
|
+
enums: Sonamu.apiRootPath + "/src/application/**/*.enums.ts",
|
|
347
|
+
generated: Sonamu.apiRootPath + "/src/application/**/*.generated.ts",
|
|
359
348
|
/* compiled-JS 체크 */
|
|
360
|
-
model:
|
|
361
|
-
smd:
|
|
349
|
+
model: Sonamu.apiRootPath + "/dist/application/**/*.model.js",
|
|
350
|
+
smd: Sonamu.apiRootPath + "/dist/application/**/*.smd.js",
|
|
362
351
|
};
|
|
363
352
|
|
|
364
353
|
const filePaths = (
|
|
@@ -386,19 +375,19 @@ export class Syncer {
|
|
|
386
375
|
}
|
|
387
376
|
|
|
388
377
|
async getPreviousChecksums(): Promise<PathAndChecksum[]> {
|
|
389
|
-
if (existsSync(this.
|
|
378
|
+
if (existsSync(this.checksumsPath) === false) {
|
|
390
379
|
return [];
|
|
391
380
|
}
|
|
392
381
|
|
|
393
382
|
const previousChecksums = (await readJSON(
|
|
394
|
-
this.
|
|
383
|
+
this.checksumsPath
|
|
395
384
|
)) as PathAndChecksum[];
|
|
396
385
|
return previousChecksums;
|
|
397
386
|
}
|
|
398
387
|
|
|
399
388
|
async saveChecksums(checksums: PathAndChecksum[]): Promise<void> {
|
|
400
|
-
await writeJSON(this.
|
|
401
|
-
console.debug("checksum saved", this.
|
|
389
|
+
await writeJSON(this.checksumsPath, checksums);
|
|
390
|
+
console.debug("checksum saved", this.checksumsPath);
|
|
402
391
|
}
|
|
403
392
|
|
|
404
393
|
async getChecksumOfFile(filePath: string): Promise<string> {
|
|
@@ -671,10 +660,10 @@ export class Syncer {
|
|
|
671
660
|
return printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
672
661
|
}
|
|
673
662
|
|
|
674
|
-
async autoloadApis(
|
|
663
|
+
async autoloadApis() {
|
|
675
664
|
const pathPattern = path.join(
|
|
676
|
-
|
|
677
|
-
"
|
|
665
|
+
Sonamu.apiRootPath,
|
|
666
|
+
"/src/application/**/*.model.ts"
|
|
678
667
|
);
|
|
679
668
|
// console.debug(chalk.yellow(`autoload:APIs @ ${pathPattern}`));
|
|
680
669
|
|
|
@@ -686,12 +675,10 @@ export class Syncer {
|
|
|
686
675
|
return this.apis;
|
|
687
676
|
}
|
|
688
677
|
|
|
689
|
-
async autoloadModels(
|
|
690
|
-
basePath: string
|
|
691
|
-
): Promise<{ [modelName: string]: unknown }> {
|
|
678
|
+
async autoloadModels(): Promise<{ [modelName: string]: unknown }> {
|
|
692
679
|
const pathPattern = path.join(
|
|
693
|
-
|
|
694
|
-
"
|
|
680
|
+
Sonamu.apiRootPath,
|
|
681
|
+
"dist/application/**/*.model.js"
|
|
695
682
|
);
|
|
696
683
|
// console.debug(chalk.yellow(`autoload:models @ ${pathPattern}`));
|
|
697
684
|
|
|
@@ -700,22 +687,21 @@ export class Syncer {
|
|
|
700
687
|
const functions = modules
|
|
701
688
|
.map(({ imported }) => Object.entries(imported))
|
|
702
689
|
.flat();
|
|
703
|
-
|
|
690
|
+
this.models = Object.fromEntries(
|
|
704
691
|
functions.filter(([name]) => name.endsWith("Model"))
|
|
705
692
|
);
|
|
693
|
+
return this.models;
|
|
706
694
|
}
|
|
707
695
|
|
|
708
|
-
async autoloadTypes(
|
|
709
|
-
basePath: string
|
|
710
|
-
): Promise<{ [typeName: string]: z.ZodObject<any> }> {
|
|
696
|
+
async autoloadTypes(): Promise<{ [typeName: string]: z.ZodObject<any> }> {
|
|
711
697
|
if (Object.keys(this.types).length > 0) {
|
|
712
698
|
return this.types;
|
|
713
699
|
}
|
|
714
700
|
|
|
715
701
|
const pathPatterns = [
|
|
716
|
-
path.join(
|
|
717
|
-
path.join(
|
|
718
|
-
path.join(
|
|
702
|
+
path.join(Sonamu.apiRootPath, "/dist/application/**/*.types.js"),
|
|
703
|
+
path.join(Sonamu.apiRootPath, "/dist/application/**/*.enums.js"),
|
|
704
|
+
path.join(Sonamu.apiRootPath, "/dist/application/**/*.generated.js"),
|
|
719
705
|
];
|
|
720
706
|
// console.debug(chalk.magenta(`autoload:types @ ${pathPatterns.join("\n")}`));
|
|
721
707
|
|
|
@@ -784,9 +770,9 @@ export class Syncer {
|
|
|
784
770
|
if (key === "service" || key === "generated_http") {
|
|
785
771
|
// service 필요 정보 (API 리스트)
|
|
786
772
|
const smd = SMDManager.get(options.smdId);
|
|
787
|
-
const modelTsPath = `${path.
|
|
788
|
-
|
|
789
|
-
"
|
|
773
|
+
const modelTsPath = `${path.join(
|
|
774
|
+
Sonamu.apiRootPath,
|
|
775
|
+
"/src/application"
|
|
790
776
|
)}/${smd.names.fs}/${smd.names.fs}.model.ts`;
|
|
791
777
|
extra = [await this.readApisFromFile(modelTsPath)];
|
|
792
778
|
} else if (key === "view_list" || key === "model") {
|
|
@@ -890,8 +876,9 @@ export class Syncer {
|
|
|
890
876
|
}
|
|
891
877
|
|
|
892
878
|
async writeCodeToPath(pathAndCode: PathAndCode): Promise<string[]> {
|
|
893
|
-
const {
|
|
894
|
-
const
|
|
879
|
+
const { targets } = Sonamu.config.sync;
|
|
880
|
+
const { appRootPath } = Sonamu;
|
|
881
|
+
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
895
882
|
|
|
896
883
|
const dstFilePaths = uniq(
|
|
897
884
|
targets.map((target) => filePath.replace("/:target/", `/${target}/`))
|
|
@@ -903,7 +890,10 @@ export class Syncer {
|
|
|
903
890
|
mkdirSync(dir, { recursive: true });
|
|
904
891
|
}
|
|
905
892
|
writeFileSync(dstFilePath, pathAndCode.code);
|
|
906
|
-
console.log(
|
|
893
|
+
console.log(
|
|
894
|
+
"GENERATED ",
|
|
895
|
+
chalk.blue(dstFilePath.replace(appRootPath + "/", ""))
|
|
896
|
+
);
|
|
907
897
|
return dstFilePath;
|
|
908
898
|
})
|
|
909
899
|
);
|
|
@@ -949,8 +939,8 @@ export class Syncer {
|
|
|
949
939
|
} else {
|
|
950
940
|
filteredPathAndCodes = pathAndCodes.filter((pathAndCode, index) => {
|
|
951
941
|
if (index === 0) {
|
|
952
|
-
const {
|
|
953
|
-
const filePath = `${appRootPath}/${pathAndCode.path}`;
|
|
942
|
+
const { targets } = Sonamu.config.sync;
|
|
943
|
+
const filePath = `${Sonamu.appRootPath}/${pathAndCode.path}`;
|
|
954
944
|
const dstFilePaths = targets.map((target) =>
|
|
955
945
|
filePath.replace("/:target/", `/${target}/`)
|
|
956
946
|
);
|
|
@@ -991,21 +981,22 @@ export class Syncer {
|
|
|
991
981
|
enumsKeys.map((componentId) => {
|
|
992
982
|
const { target, path: p } = tpl.getTargetAndPath(names, componentId);
|
|
993
983
|
result[`${key}__${componentId}`] = existsSync(
|
|
994
|
-
path.join(
|
|
984
|
+
path.join(Sonamu.appRootPath, target, p)
|
|
995
985
|
);
|
|
996
986
|
});
|
|
997
987
|
return result;
|
|
998
988
|
}
|
|
999
989
|
|
|
1000
990
|
const { target, path: p } = tpl.getTargetAndPath(names);
|
|
991
|
+
const { targets } = Sonamu.config.sync;
|
|
1001
992
|
if (target.includes(":target")) {
|
|
1002
|
-
|
|
993
|
+
targets.map((t) => {
|
|
1003
994
|
result[`${key}__${t}`] = existsSync(
|
|
1004
|
-
path.join(
|
|
995
|
+
path.join(Sonamu.appRootPath, target.replace(":target", t), p)
|
|
1005
996
|
);
|
|
1006
997
|
});
|
|
1007
998
|
} else {
|
|
1008
|
-
result[key] = existsSync(path.join(
|
|
999
|
+
result[key] = existsSync(path.join(Sonamu.appRootPath, target, p));
|
|
1009
1000
|
}
|
|
1010
1001
|
|
|
1011
1002
|
return result;
|
|
@@ -1015,8 +1006,7 @@ export class Syncer {
|
|
|
1015
1006
|
async getZodTypeById(zodTypeId: string): Promise<z.ZodTypeAny> {
|
|
1016
1007
|
const modulePath = SMDManager.getModulePath(zodTypeId);
|
|
1017
1008
|
const moduleAbsPath = path.join(
|
|
1018
|
-
|
|
1019
|
-
"api",
|
|
1009
|
+
Sonamu.apiRootPath,
|
|
1020
1010
|
"dist",
|
|
1021
1011
|
"application",
|
|
1022
1012
|
modulePath + ".js"
|
|
@@ -7,7 +7,7 @@ import { ExtendedApi } from "../api/decorators";
|
|
|
7
7
|
import { Template } from "./base-template";
|
|
8
8
|
import prettier from "prettier";
|
|
9
9
|
import { DateTime } from "luxon";
|
|
10
|
-
import {
|
|
10
|
+
import { Sonamu } from "../api/sonamu";
|
|
11
11
|
|
|
12
12
|
export class Template__generated_http extends Template {
|
|
13
13
|
constructor() {
|
|
@@ -23,7 +23,7 @@ export class Template__generated_http extends Template {
|
|
|
23
23
|
|
|
24
24
|
render({ smdId }: TemplateOptions["generated"], apis: ExtendedApi[]) {
|
|
25
25
|
const names = SMDManager.getNamesFromId(smdId);
|
|
26
|
-
const references =
|
|
26
|
+
const references = Sonamu.syncer.types;
|
|
27
27
|
|
|
28
28
|
const lines = apis.map((api) => {
|
|
29
29
|
const reqObject = this.resolveApiParams(api, references);
|