@simplysm/sd-cli 7.0.263 → 7.0.266

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.
Files changed (78) hide show
  1. package/README.md +69 -22
  2. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-128x128.png +0 -0
  3. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-144x144.png +0 -0
  4. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-152x152.png +0 -0
  5. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-192x192.png +0 -0
  6. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-384x384.png +0 -0
  7. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-512x512.png +0 -0
  8. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-72x72.png +0 -0
  9. package/{src/entry-points/file/assets → assets/client-files}/assets/icons/icon-96x96.png +0 -0
  10. package/{src/entry-points/file/assets → assets/client-files}/favicon.ico +0 -0
  11. package/dist/bin/sd-cli.mjs +44 -5
  12. package/dist/build-tool/SdCliCordova.mjs +3 -3
  13. package/dist/build-tool/SdCliIndexFileGenerator.mjs +2 -3
  14. package/dist/builder/SdCliClientBuilder.d.ts +2 -0
  15. package/dist/builder/SdCliClientBuilder.mjs +45 -12
  16. package/dist/builder/SdCliServerBuilder.d.ts +2 -0
  17. package/dist/builder/SdCliServerBuilder.mjs +27 -13
  18. package/dist/entry-points/SdCliPrepare.mjs +34 -34
  19. package/dist/entry-points/SdCliProjectGenerator.d.ts +7 -0
  20. package/dist/entry-points/SdCliProjectGenerator.mjs +65 -33
  21. package/dist/entry-points/file/base/fc_package_eslintrc.mjs +11 -11
  22. package/dist/entry-points/file/base/fc_package_tsconfig.d.ts +1 -0
  23. package/dist/entry-points/file/base/fc_package_tsconfig.mjs +3 -2
  24. package/dist/entry-points/file/client/fc_package_AppModule.mjs +1 -1
  25. package/dist/entry-points/file/client/fc_package_AppPage.mjs +2 -22
  26. package/dist/entry-points/file/client/fc_package_Page.d.ts +4 -0
  27. package/dist/entry-points/file/client/fc_package_Page.mjs +19 -0
  28. package/dist/entry-points/file/project/fc_project_gitignore.mjs +1 -1
  29. package/dist/entry-points/file/project/fc_project_readme.mjs +3 -2
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.mjs +2 -2
  32. package/dist/ng-tools/SdCliNgModuleGenerator.mjs +35 -36
  33. package/dist/packages/SdCliPackage.mjs +2 -2
  34. package/docs/client-add-page.md +8 -0
  35. package/docs/client-router.md +85 -0
  36. package/docs/client-sw.md +101 -0
  37. package/docs/conf-orm.md +81 -0
  38. package/docs/conf-usage.md +5 -0
  39. package/docs/lib-local-update.md +50 -0
  40. package/docs/lib-ts-paths.md +25 -0
  41. package/package.json +6 -6
  42. package/src/SdCliBuildResultError.ts +9 -9
  43. package/src/bin/sd-cli.ts +48 -5
  44. package/src/build-tool/SdCliCacheCompilerHost.ts +77 -77
  45. package/src/build-tool/SdCliCordova.ts +2 -2
  46. package/src/build-tool/SdCliGithubApi.ts +110 -110
  47. package/src/build-tool/SdCliIndexFileGenerator.ts +79 -80
  48. package/src/build-tool/SdCliNgCacheCompilerHost.ts +58 -58
  49. package/src/build-tool/SdCliPackageLinter.ts +74 -74
  50. package/src/builder/SdCliClientBuilder.ts +58 -13
  51. package/src/builder/SdCliServerBuilder.ts +34 -14
  52. package/src/entry-points/SdCliFileCrypto.ts +87 -87
  53. package/src/entry-points/SdCliPrepare.ts +55 -55
  54. package/src/entry-points/SdCliProjectGenerator.ts +80 -38
  55. package/src/entry-points/file/base/fc_package_eslintrc.ts +10 -10
  56. package/src/entry-points/file/base/fc_package_tsconfig.ts +3 -2
  57. package/src/entry-points/file/client/fc_package_AppModule.ts +1 -1
  58. package/src/entry-points/file/client/fc_package_AppPage.ts +1 -21
  59. package/src/entry-points/file/client/fc_package_Page.ts +19 -0
  60. package/src/entry-points/file/project/fc_project_gitignore.ts +1 -1
  61. package/src/entry-points/file/project/fc_project_readme.ts +2 -1
  62. package/src/index.ts +55 -55
  63. package/src/ng-tools/SdCliNgModuleGenerator.ts +639 -640
  64. package/src/ng-tools/babel/SdCliBbFileMetadata.ts +568 -568
  65. package/src/ng-tools/babel/SdCliBbRootMetadata.ts +239 -239
  66. package/src/ng-tools/babel/SdCliBbUtil.ts +15 -15
  67. package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +234 -234
  68. package/src/ng-tools/babel/TSdCliBbTypeMetadata.ts +177 -177
  69. package/src/ng-tools/commons.ts +3 -3
  70. package/src/ng-tools/typescript/SdCliTsFileMetadata.ts +384 -384
  71. package/src/ng-tools/typescript/SdCliTsRootMetadata.ts +32 -32
  72. package/src/ng-tools/typescript/SdCliTsUtil.ts +29 -29
  73. package/src/packages/SdCliPackage.ts +1 -1
  74. package/src/utils/SdCliConfigUtil.ts +94 -94
  75. package/src/utils/SdCliNpmConfigUtil.ts +16 -16
  76. package/dist/entry-points/file/client/fc_package_appicons.d.ts +0 -1
  77. package/dist/entry-points/file/client/fc_package_appicons.mjs +0 -6
  78. 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
- ...opt,
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
- useAutoIndex: true
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
- useAutoIndex: true
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`), fc_package_DbModel({
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
- "@fortawesome/angular-fontawesome": "^0.10.2",
240
- "@fortawesome/fontawesome-svg-core": "^6.1.0",
241
- "@fortawesome/free-brands-svg-icons": "^6.1.0",
242
- "@fortawesome/pro-duotone-svg-icons": "^6.1.0",
243
- "@fortawesome/pro-light-svg-icons": "^6.1.0",
244
- "@fortawesome/pro-regular-svg-icons": "^6.1.0",
245
- "@fortawesome/pro-solid-svg-icons": "^6.1.0",
246
- "@simplysm/sd-angular": "~7.0.0",
247
- "@simplysm/sd-core-browser": "~7.0.0",
248
- "@simplysm/sd-core-common": "~7.0.0",
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)), "file/assets"),
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
- private async _addPackageBaseTemplate(opt: { name: string; description: string; useDom: boolean; isModule: boolean; isForAngular: boolean; main?: string; types?: string; dependencies: Record<string, string> }): Promise<void> {
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: opt.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; useAutoIndex: boolean; serverName?: string }): Promise<void> {
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.useAutoIndex ? { autoIndex: {} } : {},
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
- },${opt.isForAngular ? `
18
- {
19
- files: ["*.ts"],
20
- extends: ["plugin:@simplysm/angular"]
21
- },
22
- {
23
- files: ["*.html"],
24
- extends: ["plugin:@simplysm/angular-template"]
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 async ngDoBootstrap(appRef: ApplicationRef): Promise<void> {
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, HostListener } from "@angular/core";
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();
@@ -11,6 +11,6 @@ _logs
11
11
  _modules
12
12
  _routes.ts
13
13
  ~$*.xlsx
14
- .*
14
+ .*/
15
15
 
16
16
  `.trim();
@@ -3,9 +3,10 @@ export const fc_project_readme = (opt: { description: string }): string => /* la
3
3
 
4
4
  ## Requirements
5
5
 
6
- * node@16.x.x
6
+ * node v16.x.x
7
7
 
8
8
  ## Installation
9
9
 
10
10
  npm install
11
+
11
12
  `.trim();