@simplysm/sd-cli 7.0.263 → 7.0.268
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/README.md +70 -23
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-128x128.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-144x144.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-152x152.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-192x192.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-384x384.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-512x512.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-72x72.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-96x96.png +0 -0
- package/{src/entry-points/file/assets → assets/client-files}/favicon.ico +0 -0
- package/dist/bin/sd-cli.mjs +48 -9
- package/dist/build-tool/SdCliCordova.mjs +2 -2
- package/dist/build-tool/SdCliIndexFileGenerator.mjs +2 -3
- package/dist/builder/SdCliClientBuilder.d.ts +2 -0
- package/dist/builder/SdCliClientBuilder.mjs +47 -14
- package/dist/builder/SdCliServerBuilder.d.ts +2 -0
- package/dist/builder/SdCliServerBuilder.mjs +27 -13
- package/dist/entry-points/SdCliPrepare.mjs +34 -34
- package/dist/entry-points/SdCliProjectGenerator.d.ts +7 -0
- package/dist/entry-points/SdCliProjectGenerator.mjs +65 -33
- package/dist/entry-points/file/base/fc_package_eslintrc.mjs +11 -11
- package/dist/entry-points/file/base/fc_package_tsconfig.d.ts +1 -0
- package/dist/entry-points/file/base/fc_package_tsconfig.mjs +3 -2
- package/dist/entry-points/file/client/fc_package_AppModule.mjs +1 -1
- package/dist/entry-points/file/client/fc_package_AppPage.mjs +2 -22
- package/dist/entry-points/file/client/fc_package_Page.d.ts +4 -0
- package/dist/entry-points/file/client/fc_package_Page.mjs +19 -0
- package/dist/entry-points/file/project/fc_project_gitignore.mjs +1 -1
- package/dist/entry-points/file/project/fc_project_readme.mjs +3 -2
- package/dist/entry-points/file/project/fc_project_tsconfig.mjs +1 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +2 -2
- package/dist/ng-tools/SdCliNgModuleGenerator.mjs +35 -36
- package/dist/packages/SdCliPackage.mjs +2 -2
- package/docs/client-add-page.md +8 -0
- package/docs/client-router.md +85 -0
- package/docs/client-sw.md +101 -0
- package/docs/conf-orm.md +81 -0
- package/docs/conf-usage.md +5 -0
- package/docs/lib-local-update.md +50 -0
- package/docs/lib-ts-paths.md +25 -0
- package/package.json +6 -6
- package/src/SdCliBuildResultError.ts +9 -9
- package/src/bin/sd-cli.ts +52 -9
- package/src/build-tool/SdCliCacheCompilerHost.ts +77 -77
- package/src/build-tool/SdCliCordova.ts +1 -1
- package/src/build-tool/SdCliGithubApi.ts +110 -110
- package/src/build-tool/SdCliIndexFileGenerator.ts +79 -80
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +58 -58
- package/src/build-tool/SdCliPackageLinter.ts +74 -74
- package/src/builder/SdCliClientBuilder.ts +60 -15
- package/src/builder/SdCliServerBuilder.ts +34 -14
- package/src/entry-points/SdCliFileCrypto.ts +87 -87
- package/src/entry-points/SdCliPrepare.ts +55 -55
- package/src/entry-points/SdCliProjectGenerator.ts +80 -38
- package/src/entry-points/file/base/fc_package_eslintrc.ts +10 -10
- package/src/entry-points/file/base/fc_package_tsconfig.ts +3 -2
- package/src/entry-points/file/client/fc_package_AppModule.ts +1 -1
- package/src/entry-points/file/client/fc_package_AppPage.ts +1 -21
- package/src/entry-points/file/client/fc_package_Page.ts +19 -0
- package/src/entry-points/file/project/fc_project_gitignore.ts +1 -1
- package/src/entry-points/file/project/fc_project_readme.ts +2 -1
- package/src/entry-points/file/project/fc_project_tsconfig.ts +0 -1
- package/src/index.ts +55 -55
- package/src/ng-tools/SdCliNgModuleGenerator.ts +639 -640
- package/src/ng-tools/babel/SdCliBbFileMetadata.ts +568 -568
- package/src/ng-tools/babel/SdCliBbRootMetadata.ts +239 -239
- package/src/ng-tools/babel/SdCliBbUtil.ts +15 -15
- package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +234 -234
- package/src/ng-tools/babel/TSdCliBbTypeMetadata.ts +177 -177
- package/src/ng-tools/commons.ts +3 -3
- package/src/ng-tools/typescript/SdCliTsFileMetadata.ts +384 -384
- package/src/ng-tools/typescript/SdCliTsRootMetadata.ts +32 -32
- package/src/ng-tools/typescript/SdCliTsUtil.ts +29 -29
- package/src/packages/SdCliPackage.ts +1 -1
- package/src/utils/SdCliConfigUtil.ts +94 -94
- package/src/utils/SdCliNpmConfigUtil.ts +16 -16
- package/dist/entry-points/file/client/fc_package_appicons.d.ts +0 -1
- package/dist/entry-points/file/client/fc_package_appicons.mjs +0 -6
- package/src/entry-points/file/client/fc_package_appicons.ts +0 -5
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import readline from "readline";
|
|
2
|
-
import { Writable } from "stream";
|
|
3
|
-
import crypto from "crypto";
|
|
4
|
-
import { FsUtil } from "@simplysm/sd-core-node";
|
|
5
|
-
import os from "os";
|
|
6
|
-
|
|
7
|
-
export class SdCliFileCrypto {
|
|
8
|
-
public async encryptAsync(filePath: string): Promise<void> {
|
|
9
|
-
if (!FsUtil.exists(filePath)) {
|
|
10
|
-
throw new Error(`파일 '${filePath}'을 찾을 수 없습니다.`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const key = await this._readKeyAsync("password: ");
|
|
14
|
-
if (!key) {
|
|
15
|
-
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const confirmKey = await this._readKeyAsync("confirm password: ");
|
|
19
|
-
if (key !== confirmKey) {
|
|
20
|
-
throw new Error("암호화키가 서로 다릅니다.");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
this._encryptFile(filePath, key, filePath + ".enc");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
public async decryptAsync(encFilePath: string): Promise<void> {
|
|
27
|
-
if (!FsUtil.exists(encFilePath)) {
|
|
28
|
-
throw new Error(`파일 '${encFilePath}'을 찾을 수 없습니다.`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (!encFilePath.endsWith(".enc")) {
|
|
32
|
-
throw new Error(`파일 ${encFilePath}의 확장자가 '.enc'가 아닙니다.`);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const resultFilePath = encFilePath.slice(0, -4);
|
|
36
|
-
if (FsUtil.exists(resultFilePath)) {
|
|
37
|
-
process.stdout.write(`복호화 시, 현재 존재하는 '${resultFilePath}'파일을 덮어씁니다.${os.EOL}`, "utf-8");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const key = await this._readKeyAsync("password: ");
|
|
41
|
-
if (!key) {
|
|
42
|
-
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this._decryptFile(encFilePath, key, resultFilePath);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
private _encryptFile(filePath: string, key: string, encFilePath: string): void {
|
|
49
|
-
const iv = Buffer.alloc(16, 0);
|
|
50
|
-
const cipheriv = crypto.createCipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
51
|
-
|
|
52
|
-
const input = FsUtil.createReadStream(filePath);
|
|
53
|
-
const output = FsUtil.createWriteStream(encFilePath);
|
|
54
|
-
input.pipe(cipheriv).pipe(output);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private _decryptFile(encFilePath: string, key: string, filePath: string): void {
|
|
58
|
-
const iv = Buffer.alloc(16, 0);
|
|
59
|
-
const cipheriv = crypto.createDecipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
60
|
-
|
|
61
|
-
const input = FsUtil.createReadStream(encFilePath);
|
|
62
|
-
const output = FsUtil.createWriteStream(filePath);
|
|
63
|
-
input.pipe(cipheriv).pipe(output);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private async _readKeyAsync(message: string): Promise<string> {
|
|
67
|
-
process.stdout.write(message, "utf-8");
|
|
68
|
-
|
|
69
|
-
return await new Promise((resolve) => {
|
|
70
|
-
const rl = readline.createInterface({
|
|
71
|
-
input: process.stdin,
|
|
72
|
-
output: new Writable({
|
|
73
|
-
write: (chunk, encoding, callback) => {
|
|
74
|
-
callback();
|
|
75
|
-
}
|
|
76
|
-
}),
|
|
77
|
-
terminal: true
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
rl.question(message, (answer) => {
|
|
81
|
-
process.stdout.write(os.EOL, "utf-8");
|
|
82
|
-
resolve(answer);
|
|
83
|
-
rl.close();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
1
|
+
import readline from "readline";
|
|
2
|
+
import { Writable } from "stream";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
import { FsUtil } from "@simplysm/sd-core-node";
|
|
5
|
+
import os from "os";
|
|
6
|
+
|
|
7
|
+
export class SdCliFileCrypto {
|
|
8
|
+
public async encryptAsync(filePath: string): Promise<void> {
|
|
9
|
+
if (!FsUtil.exists(filePath)) {
|
|
10
|
+
throw new Error(`파일 '${filePath}'을 찾을 수 없습니다.`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const key = await this._readKeyAsync("password: ");
|
|
14
|
+
if (!key) {
|
|
15
|
+
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const confirmKey = await this._readKeyAsync("confirm password: ");
|
|
19
|
+
if (key !== confirmKey) {
|
|
20
|
+
throw new Error("암호화키가 서로 다릅니다.");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this._encryptFile(filePath, key, filePath + ".enc");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async decryptAsync(encFilePath: string): Promise<void> {
|
|
27
|
+
if (!FsUtil.exists(encFilePath)) {
|
|
28
|
+
throw new Error(`파일 '${encFilePath}'을 찾을 수 없습니다.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!encFilePath.endsWith(".enc")) {
|
|
32
|
+
throw new Error(`파일 ${encFilePath}의 확장자가 '.enc'가 아닙니다.`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const resultFilePath = encFilePath.slice(0, -4);
|
|
36
|
+
if (FsUtil.exists(resultFilePath)) {
|
|
37
|
+
process.stdout.write(`복호화 시, 현재 존재하는 '${resultFilePath}'파일을 덮어씁니다.${os.EOL}`, "utf-8");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const key = await this._readKeyAsync("password: ");
|
|
41
|
+
if (!key) {
|
|
42
|
+
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this._decryptFile(encFilePath, key, resultFilePath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _encryptFile(filePath: string, key: string, encFilePath: string): void {
|
|
49
|
+
const iv = Buffer.alloc(16, 0);
|
|
50
|
+
const cipheriv = crypto.createCipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
51
|
+
|
|
52
|
+
const input = FsUtil.createReadStream(filePath);
|
|
53
|
+
const output = FsUtil.createWriteStream(encFilePath);
|
|
54
|
+
input.pipe(cipheriv).pipe(output);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private _decryptFile(encFilePath: string, key: string, filePath: string): void {
|
|
58
|
+
const iv = Buffer.alloc(16, 0);
|
|
59
|
+
const cipheriv = crypto.createDecipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
60
|
+
|
|
61
|
+
const input = FsUtil.createReadStream(encFilePath);
|
|
62
|
+
const output = FsUtil.createWriteStream(filePath);
|
|
63
|
+
input.pipe(cipheriv).pipe(output);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private async _readKeyAsync(message: string): Promise<string> {
|
|
67
|
+
process.stdout.write(message, "utf-8");
|
|
68
|
+
|
|
69
|
+
return await new Promise((resolve) => {
|
|
70
|
+
const rl = readline.createInterface({
|
|
71
|
+
input: process.stdin,
|
|
72
|
+
output: new Writable({
|
|
73
|
+
write: (chunk, encoding, callback) => {
|
|
74
|
+
callback();
|
|
75
|
+
}
|
|
76
|
+
}),
|
|
77
|
+
terminal: true
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
rl.question(message, (answer) => {
|
|
81
|
+
process.stdout.write(os.EOL, "utf-8");
|
|
82
|
+
resolve(answer);
|
|
83
|
+
rl.close();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import { FsUtil, Logger } from "@simplysm/sd-core-node";
|
|
2
|
-
import { fileURLToPath } from "url";
|
|
3
|
-
|
|
4
|
-
export class SdCliPrepare {
|
|
5
|
-
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
6
|
-
|
|
7
|
-
public async prepareAsync(): Promise<void> {
|
|
8
|
-
// 타입체크 속도 지연 메시지 추가
|
|
9
|
-
const r1 = await this._modifyTypescriptCodeForTypeCheckPerformanceWarning();
|
|
10
|
-
this._logger.log(`[모듈수정] 타입체크 속도 지연 메시지 추가 (${r1 ? "O" : "X"})`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
private async _modifyTypescriptCodeForTypeCheckPerformanceWarning(): Promise<boolean> {
|
|
14
|
-
const fileUrl = await import.meta.resolve!("typescript");
|
|
15
|
-
const filePath = fileURLToPath(fileUrl);
|
|
16
|
-
const fileContent = await FsUtil.readFileAsync(filePath);
|
|
17
|
-
const modifiedFileContent = fileContent.replace(`
|
|
18
|
-
function checkSourceElement(node) {
|
|
19
|
-
if (node) {
|
|
20
|
-
var saveCurrentNode = currentNode;
|
|
21
|
-
currentNode = node;
|
|
22
|
-
instantiationCount = 0;
|
|
23
|
-
checkSourceElementWorker(node);
|
|
24
|
-
currentNode = saveCurrentNode;
|
|
25
|
-
}
|
|
26
|
-
}`, `
|
|
27
|
-
function checkSourceElement(node) {
|
|
28
|
-
if (node) {
|
|
29
|
-
const prevUsage = process.cpuUsage();
|
|
30
|
-
|
|
31
|
-
var saveCurrentNode = currentNode;
|
|
32
|
-
currentNode = node;
|
|
33
|
-
instantiationCount = 0;
|
|
34
|
-
checkSourceElementWorker(node);
|
|
35
|
-
currentNode = saveCurrentNode;
|
|
36
|
-
|
|
37
|
-
const usage = process.cpuUsage(prevUsage);
|
|
38
|
-
if (node.hasChildPerformanceWarning) {
|
|
39
|
-
node.parent.hasChildPerformanceWarning = true;
|
|
40
|
-
}
|
|
41
|
-
else if (usage.user + usage.system > 1000 * 1000 && node.kind !== 253) {
|
|
42
|
-
error(node, {
|
|
43
|
-
code: 9000,
|
|
44
|
-
category: ts.DiagnosticCategory.Warning,
|
|
45
|
-
key: "simplysm_check_source_element_performance_slow",
|
|
46
|
-
message: "소스코드 타입분석에 너무 오랜 시간이 소요됩니다. [" + Math.round((usage.user + usage.system) / 1000) + "ms/cpu, KIND: " + node.kind + "]"
|
|
47
|
-
});
|
|
48
|
-
node.parent.hasChildPerformanceWarning = true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}`);
|
|
52
|
-
await FsUtil.writeFileAsync(filePath, modifiedFileContent);
|
|
53
|
-
return modifiedFileContent.includes("const prevUsage = process.cpuUsage();");
|
|
54
|
-
}
|
|
55
|
-
}
|
|
1
|
+
import { FsUtil, Logger } from "@simplysm/sd-core-node";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
|
|
4
|
+
export class SdCliPrepare {
|
|
5
|
+
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
6
|
+
|
|
7
|
+
public async prepareAsync(): Promise<void> {
|
|
8
|
+
// 타입체크 속도 지연 메시지 추가
|
|
9
|
+
const r1 = await this._modifyTypescriptCodeForTypeCheckPerformanceWarning();
|
|
10
|
+
this._logger.log(`[모듈수정] 타입체크 속도 지연 메시지 추가 (${r1 ? "O" : "X"})`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
private async _modifyTypescriptCodeForTypeCheckPerformanceWarning(): Promise<boolean> {
|
|
14
|
+
const fileUrl = await import.meta.resolve!("typescript");
|
|
15
|
+
const filePath = fileURLToPath(fileUrl);
|
|
16
|
+
const fileContent = await FsUtil.readFileAsync(filePath);
|
|
17
|
+
const modifiedFileContent = fileContent.replace(`
|
|
18
|
+
function checkSourceElement(node) {
|
|
19
|
+
if (node) {
|
|
20
|
+
var saveCurrentNode = currentNode;
|
|
21
|
+
currentNode = node;
|
|
22
|
+
instantiationCount = 0;
|
|
23
|
+
checkSourceElementWorker(node);
|
|
24
|
+
currentNode = saveCurrentNode;
|
|
25
|
+
}
|
|
26
|
+
}`, `
|
|
27
|
+
function checkSourceElement(node) {
|
|
28
|
+
if (node) {
|
|
29
|
+
const prevUsage = process.cpuUsage();
|
|
30
|
+
|
|
31
|
+
var saveCurrentNode = currentNode;
|
|
32
|
+
currentNode = node;
|
|
33
|
+
instantiationCount = 0;
|
|
34
|
+
checkSourceElementWorker(node);
|
|
35
|
+
currentNode = saveCurrentNode;
|
|
36
|
+
|
|
37
|
+
const usage = process.cpuUsage(prevUsage);
|
|
38
|
+
if (node.hasChildPerformanceWarning) {
|
|
39
|
+
node.parent.hasChildPerformanceWarning = true;
|
|
40
|
+
}
|
|
41
|
+
else if (usage.user + usage.system > 1000 * 1000 && node.kind !== 253) {
|
|
42
|
+
error(node, {
|
|
43
|
+
code: 9000,
|
|
44
|
+
category: ts.DiagnosticCategory.Warning,
|
|
45
|
+
key: "simplysm_check_source_element_performance_slow",
|
|
46
|
+
message: "소스코드 타입분석에 너무 오랜 시간이 소요됩니다. [" + Math.round((usage.user + usage.system) / 1000) + "ms/cpu, KIND: " + node.kind + "]"
|
|
47
|
+
});
|
|
48
|
+
node.parent.hasChildPerformanceWarning = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}`);
|
|
52
|
+
await FsUtil.writeFileAsync(filePath, modifiedFileContent);
|
|
53
|
+
return modifiedFileContent.includes("const prevUsage = process.cpuUsage();");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -15,7 +15,6 @@ import { fc_package_tsconfig } from "./file/base/fc_package_tsconfig";
|
|
|
15
15
|
import { fc_package_DbContext } from "./file/db/fc_package_DbContext";
|
|
16
16
|
import { fc_package_DbModel } from "./file/db/fc_package_DbModel";
|
|
17
17
|
import { fc_package_server_main } from "./file/server/fc_package_server_main";
|
|
18
|
-
import { fc_package_appicons } from "./file/client/fc_package_appicons";
|
|
19
18
|
import { fc_package_AppModule } from "./file/client/fc_package_AppModule";
|
|
20
19
|
import { fc_package_AppPage } from "./file/client/fc_package_AppPage";
|
|
21
20
|
import { fileURLToPath } from "url";
|
|
@@ -25,6 +24,8 @@ import { fc_package_manifest } from "./file/client/fc_package_manifest";
|
|
|
25
24
|
import { INpmConfig } from "../commons";
|
|
26
25
|
import { fc_package_polyfills } from "./file/client/fc_package_polyfills";
|
|
27
26
|
import { fc_package_styles } from "./file/client/fc_package_styles";
|
|
27
|
+
import { ISdAutoIndexConfig } from "../build-tool/SdCliIndexFileGenerator";
|
|
28
|
+
import { fc_package_Page } from "./file/client/fc_package_Page";
|
|
28
29
|
|
|
29
30
|
export class SdCliProjectGenerator {
|
|
30
31
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
@@ -83,14 +84,20 @@ export class SdCliProjectGenerator {
|
|
|
83
84
|
await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
public async addTsLibAsync(opt: { name: string; description: string; useDom: boolean }): Promise<void> {
|
|
87
|
+
public async addTsLibAsync(opt: { name: string; description: string; useDom: boolean; isForAngular: boolean }): Promise<void> {
|
|
88
|
+
const projNpmConfig = await this._getProjNpmConfigAsync();
|
|
89
|
+
const projName = projNpmConfig.name;
|
|
90
|
+
|
|
87
91
|
await this._addPackageBaseTemplate({
|
|
88
|
-
|
|
92
|
+
name: opt.name,
|
|
93
|
+
description: opt.description,
|
|
94
|
+
useDom: opt.isForAngular || opt.useDom,
|
|
95
|
+
isForAngular: opt.isForAngular,
|
|
89
96
|
isModule: true,
|
|
90
|
-
isForAngular: false,
|
|
91
97
|
types: "dist/index.d.ts",
|
|
92
98
|
main: "dist/index.mjs",
|
|
93
|
-
dependencies: {}
|
|
99
|
+
dependencies: {},
|
|
100
|
+
tsconfigOptions: {}
|
|
94
101
|
});
|
|
95
102
|
|
|
96
103
|
this._logger.log(`[${opt.name}] 'simplysm.json' 파일에 등록`);
|
|
@@ -98,8 +105,18 @@ export class SdCliProjectGenerator {
|
|
|
98
105
|
await this._addPackageToSimplysmJson({
|
|
99
106
|
name: opt.name,
|
|
100
107
|
type: "library",
|
|
101
|
-
|
|
108
|
+
autoIndex: {
|
|
109
|
+
...opt.isForAngular ? {
|
|
110
|
+
polyfills: [
|
|
111
|
+
"@simplysm/sd-core-common",
|
|
112
|
+
"@simplysm/sd-core-browser"
|
|
113
|
+
]
|
|
114
|
+
} : {}
|
|
115
|
+
},
|
|
102
116
|
});
|
|
117
|
+
|
|
118
|
+
this._logger.log(`[${projName}] npm install`);
|
|
119
|
+
await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
|
|
103
120
|
}
|
|
104
121
|
|
|
105
122
|
public async addDbLibAsync(opt: { name: string }): Promise<void> {
|
|
@@ -119,7 +136,8 @@ export class SdCliProjectGenerator {
|
|
|
119
136
|
dependencies: {
|
|
120
137
|
"@simplysm/sd-core-common": "~7.0.0",
|
|
121
138
|
"@simplysm/sd-orm-common": "~7.0.0"
|
|
122
|
-
}
|
|
139
|
+
},
|
|
140
|
+
tsconfigOptions: {}
|
|
123
141
|
});
|
|
124
142
|
|
|
125
143
|
this._logger.log(`[${pkgName}] 'src/${StringUtil.toPascalCase(opt.name)}DbContext.ts' 파일 생성`);
|
|
@@ -134,7 +152,7 @@ export class SdCliProjectGenerator {
|
|
|
134
152
|
await this._addPackageToSimplysmJson({
|
|
135
153
|
name: pkgName,
|
|
136
154
|
type: "library",
|
|
137
|
-
|
|
155
|
+
autoIndex: {}
|
|
138
156
|
});
|
|
139
157
|
|
|
140
158
|
this._logger.log(`[${projName}] npm install`);
|
|
@@ -148,10 +166,12 @@ export class SdCliProjectGenerator {
|
|
|
148
166
|
this._logger.log(`[${pkgName}] 'src/models/${opt.category}/${opt.name}.ts' 파일 생성`);
|
|
149
167
|
|
|
150
168
|
await FsUtil.writeFileAsync(
|
|
151
|
-
path.resolve(pkgPath, `src/models/${opt.category}/${opt.name}.ts`),
|
|
169
|
+
path.resolve(pkgPath, `src/models/${opt.category}/${opt.name}.ts`),
|
|
170
|
+
fc_package_DbModel({
|
|
152
171
|
name: opt.name,
|
|
153
172
|
description: opt.description
|
|
154
|
-
})
|
|
173
|
+
})
|
|
174
|
+
);
|
|
155
175
|
|
|
156
176
|
this._logger.log(`[${pkgName}] DbContext 파일에 등록`);
|
|
157
177
|
let dbContextContent = await FsUtil.readFileAsync(path.resolve(pkgPath, `src/${StringUtil.toPascalCase(opt.dbPkgName)}DbContext.ts`));
|
|
@@ -198,7 +218,8 @@ export class SdCliProjectGenerator {
|
|
|
198
218
|
"@simplysm/sd-core-node": "~7.0.0",
|
|
199
219
|
"@simplysm/sd-service-common": "~7.0.0",
|
|
200
220
|
"@simplysm/sd-service-server": "~7.0.0"
|
|
201
|
-
}
|
|
221
|
+
},
|
|
222
|
+
tsconfigOptions: {}
|
|
202
223
|
});
|
|
203
224
|
|
|
204
225
|
this._logger.log(`[${pkgName}] 'src/main.ts' 파일 등록`);
|
|
@@ -210,8 +231,7 @@ export class SdCliProjectGenerator {
|
|
|
210
231
|
this._logger.log(`[${pkgName}] 'simplysm.json' 파일에 등록`);
|
|
211
232
|
await this._addPackageToSimplysmJson({
|
|
212
233
|
name: pkgName,
|
|
213
|
-
type: "server"
|
|
214
|
-
useAutoIndex: false
|
|
234
|
+
type: "server"
|
|
215
235
|
});
|
|
216
236
|
|
|
217
237
|
this._logger.log(`[${projName}] npm install`);
|
|
@@ -232,28 +252,21 @@ export class SdCliProjectGenerator {
|
|
|
232
252
|
isModule: true,
|
|
233
253
|
isForAngular: true,
|
|
234
254
|
dependencies: {
|
|
235
|
-
"@angular/common": "^13.2.0",
|
|
236
|
-
"@angular/core": "^13.2.0",
|
|
237
255
|
"@angular/platform-browser": "^13.2.0",
|
|
238
|
-
"@angular/platform-browser-dynamic": "^13.2.0"
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
"rxjs": "^6.6.7",
|
|
250
|
-
"zone.js": "~0.11.4"
|
|
256
|
+
"@angular/platform-browser-dynamic": "^13.2.0"
|
|
257
|
+
},
|
|
258
|
+
tsconfigOptions: {
|
|
259
|
+
angularCompilerOptions: {
|
|
260
|
+
"enableI18nLegacyMessageIdFormat": false,
|
|
261
|
+
"strictInjectionParameters": true,
|
|
262
|
+
"strictInputAccessModifiers": true,
|
|
263
|
+
"strictTemplates": true,
|
|
264
|
+
"strictInputTypes": false,
|
|
265
|
+
"strictOutputEventTypes": false
|
|
266
|
+
}
|
|
251
267
|
}
|
|
252
268
|
});
|
|
253
269
|
|
|
254
|
-
this._logger.log(`[${pkgName}] 'src/app-icons.ts' 파일 등록`);
|
|
255
|
-
await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/app-icons.ts"), fc_package_appicons());
|
|
256
|
-
|
|
257
270
|
this._logger.log(`[${pkgName}] 'src/AppModule.ts' 파일 등록`);
|
|
258
271
|
await FsUtil.writeFileAsync(path.resolve(pkgPath, "src/AppModule.ts"), fc_package_AppModule());
|
|
259
272
|
|
|
@@ -283,14 +296,13 @@ export class SdCliProjectGenerator {
|
|
|
283
296
|
|
|
284
297
|
this._logger.log(`[${pkgName}] 'src/assets' 파일 복사`);
|
|
285
298
|
await FsUtil.copyAsync(
|
|
286
|
-
path.resolve(path.dirname(fileURLToPath(import.meta.url)), "
|
|
299
|
+
path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../assets/client-files"),
|
|
287
300
|
path.resolve(pkgPath, "src")
|
|
288
301
|
);
|
|
289
302
|
|
|
290
303
|
await this._addPackageToSimplysmJson({
|
|
291
304
|
name: pkgName,
|
|
292
305
|
type: "client",
|
|
293
|
-
useAutoIndex: false,
|
|
294
306
|
serverName: opt.serverName
|
|
295
307
|
});
|
|
296
308
|
|
|
@@ -298,7 +310,25 @@ export class SdCliProjectGenerator {
|
|
|
298
310
|
await SdProcess.spawnAsync("npm install", { cwd: this._rootPath }, true);
|
|
299
311
|
}
|
|
300
312
|
|
|
301
|
-
|
|
313
|
+
public async addPageAsync(opt: { pkgName: string; category?: string; name: string; isRouteParent: boolean }): Promise<void> {
|
|
314
|
+
const pkgPath = path.resolve(this._rootPath, "packages", opt.pkgName);
|
|
315
|
+
|
|
316
|
+
this._logger.log(`[${opt.pkgName}] 'src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${opt.name}Page.ts' 파일 생성`);
|
|
317
|
+
await FsUtil.writeFileAsync(
|
|
318
|
+
path.resolve(pkgPath, `src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${opt.name}Page.ts`),
|
|
319
|
+
fc_package_Page({
|
|
320
|
+
name: opt.name,
|
|
321
|
+
isRouteParent: opt.isRouteParent
|
|
322
|
+
})
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
if (opt.isRouteParent) {
|
|
326
|
+
this._logger.log(`[${opt.name}] 'src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${StringUtil.toKebabCase(opt.name)}' 디렉토리 생성`);
|
|
327
|
+
await FsUtil.mkdirsAsync(path.resolve(pkgPath, `src/app/${Boolean(opt.category) ? opt.category + "/" : ""}${StringUtil.toKebabCase(opt.name)}`));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private async _addPackageBaseTemplate(opt: { name: string; description: string; useDom: boolean; isModule: boolean; isForAngular: boolean; main?: string; types?: string; dependencies: Record<string, string>; tsconfigOptions: Record<string, any> }): Promise<void> {
|
|
302
332
|
const pkgPath = path.resolve(this._rootPath, "packages", opt.name);
|
|
303
333
|
|
|
304
334
|
this._logger.log(`[${opt.name}] '.eslintrc.cjs' 파일 생성`);
|
|
@@ -314,25 +344,37 @@ export class SdCliProjectGenerator {
|
|
|
314
344
|
isModule: opt.isModule,
|
|
315
345
|
main: opt.main,
|
|
316
346
|
types: opt.types,
|
|
317
|
-
dependencies:
|
|
347
|
+
dependencies: {
|
|
348
|
+
...opt.dependencies,
|
|
349
|
+
...opt.isForAngular ? {
|
|
350
|
+
"@angular/common": "^13.2.0",
|
|
351
|
+
"@angular/core": "^13.2.0",
|
|
352
|
+
"@simplysm/sd-angular": "~7.0.0",
|
|
353
|
+
"@simplysm/sd-core-common": "~7.0.0",
|
|
354
|
+
"@simplysm/sd-core-browser": "~7.0.0",
|
|
355
|
+
"rxjs": "^6.6.7",
|
|
356
|
+
"zone.js": "~0.11.4"
|
|
357
|
+
} : {}
|
|
358
|
+
}
|
|
318
359
|
}));
|
|
319
360
|
|
|
320
361
|
this._logger.log(`[${opt.name}] 'tsconfig.json' 파일 생성`);
|
|
321
362
|
await FsUtil.writeFileAsync(path.resolve(pkgPath, "tsconfig.json"), fc_package_tsconfig({
|
|
322
363
|
isModule: opt.isModule,
|
|
323
|
-
useDom: opt.useDom
|
|
364
|
+
useDom: opt.useDom,
|
|
365
|
+
options: opt.tsconfigOptions
|
|
324
366
|
}));
|
|
325
367
|
|
|
326
368
|
this._logger.log(`[${opt.name}] 'src' 디렉토리 생성`);
|
|
327
369
|
await FsUtil.mkdirsAsync(path.resolve(pkgPath, "src"));
|
|
328
370
|
}
|
|
329
371
|
|
|
330
|
-
private async _addPackageToSimplysmJson(opt: { name: string; type: string;
|
|
372
|
+
private async _addPackageToSimplysmJson(opt: { name: string; type: string; autoIndex?: ISdAutoIndexConfig; serverName?: string }): Promise<void> {
|
|
331
373
|
const config = await FsUtil.readJsonAsync(path.resolve(this._rootPath, "simplysm.json"));
|
|
332
374
|
config.packages = config.packages ?? {};
|
|
333
375
|
config.packages[opt.name] = {
|
|
334
376
|
type: opt.type,
|
|
335
|
-
...opt.
|
|
377
|
+
...opt.autoIndex ? { autoIndex: opt.autoIndex } : {},
|
|
336
378
|
...opt.serverName !== undefined ? { server: opt.serverName } : {}
|
|
337
379
|
};
|
|
338
380
|
await FsUtil.writeJsonAsync(path.resolve(this._rootPath, "simplysm.json"), config, { space: 2 });
|
|
@@ -14,16 +14,16 @@ module.exports = {
|
|
|
14
14
|
project: require("path").resolve(__dirname, "tsconfig.json")
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
17
|
+
}
|
|
18
|
+
}${opt.isForAngular ? `,
|
|
19
|
+
{
|
|
20
|
+
files: ["*.ts"],
|
|
21
|
+
extends: ["plugin:@simplysm/angular"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
files: ["*.html"],
|
|
25
|
+
extends: ["plugin:@simplysm/angular-template"]
|
|
26
|
+
}` : ""}
|
|
27
27
|
]
|
|
28
28
|
};
|
|
29
29
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const fc_package_tsconfig = (opt: { isModule: boolean; useDom: boolean }): string => JSON.stringify({
|
|
1
|
+
export const fc_package_tsconfig = (opt: { isModule: boolean; useDom: boolean; options: Record<string, any> }): string => JSON.stringify({
|
|
2
2
|
extends: "../../tsconfig.json",
|
|
3
3
|
compilerOptions: {
|
|
4
4
|
...!opt.isModule ? { module: "CommonJS" } : {},
|
|
@@ -7,5 +7,6 @@ export const fc_package_tsconfig = (opt: { isModule: boolean; useDom: boolean })
|
|
|
7
7
|
...opt.useDom ? ["DOM"] : []
|
|
8
8
|
],
|
|
9
9
|
outDir: "./dist"
|
|
10
|
-
}
|
|
10
|
+
},
|
|
11
|
+
...opt.options
|
|
11
12
|
}, undefined, 2);
|
|
@@ -26,7 +26,7 @@ export class AppModule implements DoBootstrap {
|
|
|
26
26
|
public constructor(private readonly _toast: SdToastProvider) {
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
public
|
|
29
|
+
public ngDoBootstrap(appRef: ApplicationRef): void {
|
|
30
30
|
this._toast.alertThemes = ["danger"];
|
|
31
31
|
|
|
32
32
|
appRef.bootstrap(AppPage);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export const fc_package_AppPage = (): string => /* language=ts */ `
|
|
2
2
|
|
|
3
|
-
import { ChangeDetectionStrategy, Component
|
|
4
|
-
import { DevModal } from "./modals/DevModal";
|
|
5
|
-
import { SdModalProvider } from "@simplysm/sd-angular";
|
|
3
|
+
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
|
6
4
|
|
|
7
5
|
@Component({
|
|
8
6
|
selector: "app-root",
|
|
@@ -10,24 +8,6 @@ import { SdModalProvider } from "@simplysm/sd-angular";
|
|
|
10
8
|
template: \`APP_PAGE\`
|
|
11
9
|
})
|
|
12
10
|
export class AppPage {
|
|
13
|
-
public constructor(private readonly _modal: SdModalProvider) {
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
@HostListener("document:keydown", ["$event"])
|
|
17
|
-
public async onKeydown(event: KeyboardEvent): Promise<void> {
|
|
18
|
-
if (
|
|
19
|
-
process.env["NODE_ENV"] !== "production"
|
|
20
|
-
&& event.ctrlKey
|
|
21
|
-
&& event.altKey
|
|
22
|
-
&& event.shiftKey
|
|
23
|
-
&& event.key === "F12"
|
|
24
|
-
) {
|
|
25
|
-
event.preventDefault();
|
|
26
|
-
event.stopPropagation();
|
|
27
|
-
|
|
28
|
-
await this._modal.showAsync(DevModal, "DEV", undefined, { key: "dev-modal" });
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
11
|
}
|
|
32
12
|
|
|
33
13
|
`.trim();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { StringUtil } from "@simplysm/sd-core-common";
|
|
2
|
+
|
|
3
|
+
export const fc_package_Page = (opt: { name: string; isRouteParent: boolean }): string => /* language=ts */ `
|
|
4
|
+
|
|
5
|
+
import { ChangeDetectionStrategy, Component } from "@angular/core";
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: "app-${StringUtil.toKebabCase(opt.name)}",
|
|
9
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
10
|
+
template: \`
|
|
11
|
+
${opt.name}${opt.isRouteParent ? `<br/>
|
|
12
|
+
<router-outlet></router-outlet>
|
|
13
|
+
` : ``}
|
|
14
|
+
\`
|
|
15
|
+
})
|
|
16
|
+
export class ${opt.name}Page {
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
`.trim();
|