@simplysm/sd-cli 7.0.75 → 7.0.80

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 (45) hide show
  1. package/.eslintrc.cjs +3 -0
  2. package/dist/bin/sd-cli.mjs +38 -3
  3. package/dist/build-tool/SdCliCordova.mjs +50 -41
  4. package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +1 -0
  5. package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +11 -4
  6. package/dist/build-tool/SdCliPackageLinter.mjs +9 -5
  7. package/dist/builder/SdCliClientBuilder.d.ts +1 -0
  8. package/dist/builder/SdCliClientBuilder.mjs +44 -37
  9. package/dist/builder/SdCliJsLibBuilder.mjs +3 -3
  10. package/dist/builder/SdCliServerBuilder.d.ts +0 -1
  11. package/dist/builder/SdCliServerBuilder.mjs +13 -39
  12. package/dist/builder/SdCliTsLibBuilder.d.ts +1 -0
  13. package/dist/builder/SdCliTsLibBuilder.mjs +18 -6
  14. package/dist/commons.d.ts +2 -4
  15. package/dist/entry-points/SdCliFileCrypto.d.ts +7 -0
  16. package/dist/entry-points/SdCliFileCrypto.mjs +72 -0
  17. package/dist/entry-points/SdCliLocalUpdate.mjs +3 -3
  18. package/dist/entry-points/SdCliPrepare.mjs +1 -1
  19. package/dist/entry-points/SdCliWorkspace.mjs +2 -2
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.mjs +2 -1
  22. package/dist/ng-tools/SdCliNgModuleGenerator.mjs +1 -4
  23. package/dist/ng-tools/babel/SdCliBbFileMetadata.d.ts +1 -1
  24. package/dist/ng-tools/babel/SdCliBbFileMetadata.mjs +4 -4
  25. package/dist/ng-tools/babel/TSdCliBbNgMetadata.mjs +6 -6
  26. package/dist/utils/SdCliBuildResultUtil.mjs +4 -1
  27. package/package.json +6 -6
  28. package/src/bin/sd-cli.ts +53 -3
  29. package/src/build-tool/SdCliCordova.ts +60 -42
  30. package/src/build-tool/SdCliNgCacheCompilerHost.ts +19 -11
  31. package/src/build-tool/SdCliPackageLinter.ts +8 -4
  32. package/src/builder/SdCliClientBuilder.ts +41 -32
  33. package/src/builder/SdCliJsLibBuilder.ts +2 -2
  34. package/src/builder/SdCliServerBuilder.ts +9 -36
  35. package/src/builder/SdCliTsLibBuilder.ts +21 -5
  36. package/src/commons.ts +2 -2
  37. package/src/entry-points/SdCliFileCrypto.ts +87 -0
  38. package/src/entry-points/SdCliLocalUpdate.ts +2 -2
  39. package/src/entry-points/SdCliPrepare.ts +1 -1
  40. package/src/entry-points/SdCliWorkspace.ts +1 -1
  41. package/src/index.ts +1 -0
  42. package/src/ng-tools/SdCliNgModuleGenerator.ts +1 -4
  43. package/src/ng-tools/babel/SdCliBbFileMetadata.ts +5 -5
  44. package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +5 -5
  45. package/src/utils/SdCliBuildResultUtil.ts +4 -0
@@ -7,7 +7,6 @@ import ts from "typescript";
7
7
  import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
8
8
  import { NamedChunksPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/named-chunks-plugin";
9
9
  import {
10
- AnyComponentStyleBudgetChecker,
11
10
  CommonJsUsageWarnPlugin,
12
11
  DedupeModuleResolvePlugin,
13
12
  JavaScriptOptimizerPlugin,
@@ -23,7 +22,6 @@ import wdm from "webpack-dev-middleware";
23
22
  import whm from "webpack-hot-middleware";
24
23
  import { NextHandleFunction } from "connect";
25
24
  import { LicenseWebpackPlugin } from "license-webpack-plugin";
26
- import { Type } from "@angular-devkit/build-angular";
27
25
  import NodePolyfillPlugin from "node-polyfill-webpack-plugin";
28
26
  import { createHash } from "crypto";
29
27
  import ESLintWebpackPlugin from "eslint-webpack-plugin";
@@ -36,6 +34,7 @@ import { augmentAppWithServiceWorker } from "@angular-devkit/build-angular/src/u
36
34
  import { StringUtil } from "@simplysm/sd-core-common";
37
35
  import { SdCliNgModuleGenerator } from "../ng-tools/SdCliNgModuleGenerator";
38
36
  import { SdCliCordova } from "../build-tool/SdCliCordova";
37
+ import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
39
38
  import LintResult = ESLint.LintResult;
40
39
 
41
40
  export class SdCliClientBuilder extends EventEmitter {
@@ -48,6 +47,8 @@ export class SdCliClientBuilder extends EventEmitter {
48
47
 
49
48
  private readonly _cordova?: SdCliCordova;
50
49
 
50
+ private readonly _hasAngularRoute: boolean;
51
+
51
52
  public constructor(private readonly _rootPath: string,
52
53
  private readonly _config: ISdCliClientPackageConfig,
53
54
  private readonly _workspaceRootPath: string) {
@@ -61,6 +62,9 @@ export class SdCliClientBuilder extends EventEmitter {
61
62
  const tsconfig = FsUtil.readJson(this._tsconfigFilePath) as ITsconfig;
62
63
  this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath, tsconfig.angularCompilerOptions);
63
64
 
65
+ // isAngular
66
+ this._hasAngularRoute = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/router");
67
+
64
68
  // NgModule 생성기 초기화
65
69
  this._ngModuleGenerator = new SdCliNgModuleGenerator(this._rootPath, [
66
70
  "controls",
@@ -73,11 +77,11 @@ export class SdCliClientBuilder extends EventEmitter {
73
77
  "print-templates",
74
78
  "toasts",
75
79
  "AppPage"
76
- ], {
80
+ ], this._hasAngularRoute ? {
77
81
  glob: "**/*Page.ts",
78
82
  fileEndsWith: "Page",
79
83
  rootClassName: "AppPage"
80
- });
84
+ } : undefined);
81
85
 
82
86
  // CORDOVA
83
87
  if (this._config.cordova) {
@@ -244,7 +248,7 @@ export class SdCliClientBuilder extends EventEmitter {
244
248
  const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
245
249
 
246
250
  const pkgKey = npmConfig.name.split("/").last()!;
247
- const publicPath = `/${pkgKey}/`;
251
+ const publicPath = (this._cordova && !watch) ? `` : `/${pkgKey}/`;
248
252
 
249
253
  const cacheBasePath = path.resolve(this._rootPath, ".cache");
250
254
  const cachePath = path.resolve(cacheBasePath, pkgVersion);
@@ -257,6 +261,7 @@ export class SdCliClientBuilder extends EventEmitter {
257
261
  const polyfillsFilePath = path.resolve(this._rootPath, "src/polyfills.ts");
258
262
  const stylesFilePath = path.resolve(this._rootPath, "src/styles.scss");
259
263
 
264
+ let prevProgressMessage = "";
260
265
  return {
261
266
  mode: watch ? "development" : "production",
262
267
  devtool: false,
@@ -396,6 +401,27 @@ export class SdCliClientBuilder extends EventEmitter {
396
401
  test: /[/\\]rxjs[/\\]add[/\\].+\.js$/,
397
402
  sideEffects: true
398
403
  },
404
+ ...watch ? [
405
+ {
406
+ loader: HmrLoader,
407
+ include: [mainFilePath]
408
+ }
409
+ ] : [],
410
+ ...watch ? [
411
+ {
412
+ test: /\.[cm]?jsx?$/,
413
+ enforce: "pre" as const,
414
+ loader: "source-map-loader",
415
+ options: {
416
+ filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
417
+ const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
418
+ return !resourcePath.includes("node_modules")
419
+ || (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
420
+ || workspaceRegex.test(resourcePath);
421
+ }
422
+ }
423
+ }
424
+ ] : [],
399
425
  {
400
426
  test: /\.[cm]?[tj]sx?$/,
401
427
  resolve: { fullySpecified: false },
@@ -413,21 +439,6 @@ export class SdCliClientBuilder extends EventEmitter {
413
439
  }
414
440
  ]
415
441
  },
416
- ...watch ? [
417
- {
418
- test: /\.[cm]?jsx?$/,
419
- enforce: "pre" as const,
420
- loader: "source-map-loader",
421
- options: {
422
- filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
423
- const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
424
- return !resourcePath.includes("node_modules")
425
- || (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
426
- || workspaceRegex.test(resourcePath);
427
- }
428
- }
429
- }
430
- ] : [],
431
442
  {
432
443
  test: /\.[cm]?tsx?$/,
433
444
  loader: "@ngtools/webpack",
@@ -486,12 +497,6 @@ export class SdCliClientBuilder extends EventEmitter {
486
497
  }
487
498
  ]
488
499
  },
489
- ...watch ? [
490
- {
491
- loader: HmrLoader,
492
- include: [mainFilePath]
493
- }
494
- ] : [],
495
500
  {
496
501
  test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico|otf|xlsx?|pptx?|docx?|zip|pfx|pkl)$/,
497
502
  type: "asset/resource"
@@ -502,13 +507,17 @@ export class SdCliClientBuilder extends EventEmitter {
502
507
  new NodePolyfillPlugin(),
503
508
  new NamedChunksPlugin(),
504
509
  new DedupeModuleResolvePlugin(),
505
- /*new webpack.ProgressPlugin({
510
+ new webpack.ProgressPlugin({
506
511
  handler: (per: number, msg: string, ...args: string[]) => {
507
512
  const phaseText = msg ? ` - phase: ${msg}` : "";
508
513
  const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
509
- this._logger.debug(`Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`);
514
+ const progressMessage = `Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`;
515
+ if (progressMessage !== prevProgressMessage) {
516
+ prevProgressMessage = progressMessage;
517
+ this._logger.debug(progressMessage);
518
+ }
510
519
  }
511
- }),*/
520
+ }),
512
521
  new CommonJsUsageWarnPlugin(),
513
522
  ...watch ? [] : [
514
523
  new LicenseWebpackPlugin({
@@ -565,9 +574,9 @@ export class SdCliClientBuilder extends EventEmitter {
565
574
  emitNgModuleScope: watch,
566
575
  inlineStyleFileExtension: "scss"
567
576
  }),
568
- new AnyComponentStyleBudgetChecker(watch ? [] : [
569
- { type: Type.AnyComponentStyle, maximumWarning: "2kb", maximumError: "4kb" }
570
- ]),
577
+ // new AnyComponentStyleBudgetChecker(watch ? [] : [
578
+ // { type: Type.AnyComponentStyle, maximumWarning: "2kb", maximumError: "4kb" }
579
+ // ]),
571
580
  {
572
581
  apply: (compiler: webpack.Compiler) => {
573
582
  compiler.hooks.shutdown.tap("sass-worker", () => {
@@ -29,7 +29,7 @@ export class SdCliJsLibBuilder extends EventEmitter {
29
29
  const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
30
30
  if (changeFilePaths.length === 0) return;
31
31
 
32
- this._logger.debug("파일 변경 감지", changeInfos);
32
+ this._logger.debug("파일 변경 감지");
33
33
  this.emit("change");
34
34
  const watchBuildResults: ISdCliPackageBuildResult[] = [];
35
35
 
@@ -56,7 +56,7 @@ export class SdCliJsLibBuilder extends EventEmitter {
56
56
  }
57
57
 
58
58
  private async getRelatedPathsAsync(): Promise<string[]> {
59
- const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs|*.ts)");
59
+ const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs)");
60
60
  const mySourceFilePaths = await FsUtil.globAsync(mySourceGlobPath, {
61
61
  ignore: [
62
62
  "**/node_modules/**",
@@ -102,9 +102,6 @@ export class SdCliServerBuilder extends EventEmitter {
102
102
  // pm2.json 파일 쓰기
103
103
  await this._writeDistPm2ConfigFileAsync();
104
104
 
105
- // iis 파일 쓰기
106
- await this._writeDistIisConfigFileAsync();
107
-
108
105
  // 배포용 package.json 파일 생성
109
106
  await this._writeDistNpmConfigFileAsync(extModules.filter((item) => item.exists).map((item) => item.name));
110
107
 
@@ -155,36 +152,6 @@ export class SdCliServerBuilder extends EventEmitter {
155
152
  );
156
153
  }
157
154
 
158
- private async _writeDistIisConfigFileAsync(): Promise<void> {
159
- if (this._config.iis === undefined || this._config.iis === false) return;
160
-
161
- const iisDistPath = path.resolve(this._parsedTsconfig.options.outDir!, "web.config");
162
- const serverExeFilePath = (this._config.iis !== true && "serverExeFilePath" in this._config.iis)
163
- ? (this._config.iis.serverExeFilePath ?? "C:\\Program Files\\nodejs\\node.exe")
164
- : "C:\\Program Files\\nodejs\\node.exe";
165
- await FsUtil.writeFileAsync(iisDistPath, `
166
- <configuration>
167
- <system.webServer>
168
- <webSocket enabled="false" />
169
- <handlers>
170
- <add name="iisnode" path="main.js" verb="*" modules="iisnode" />
171
- </handlers>
172
- <iisnode nodeProcessCommandLine="${serverExeFilePath}"
173
- watchedFiles="web.config;*.js"
174
- loggingEnabled="true"
175
- devErrorsEnabled="true" />
176
- <rewrite>
177
- <rules>
178
- <rule name="main">
179
- <action type="Rewrite" url="main.mjs" />
180
- </rule>
181
- </rules>
182
- </rewrite>
183
- <httpErrors errorMode="Detailed" />
184
- </system.webServer>
185
- </configuration>`.trim());
186
- }
187
-
188
155
  private async _writeDistNpmConfigFileAsync(deps: string[]): Promise<void> {
189
156
  const distNpmConfig = ObjectUtil.clone(this._getNpmConfig(this._rootPath))!;
190
157
  distNpmConfig.dependencies = {};
@@ -225,6 +192,8 @@ export class SdCliServerBuilder extends EventEmitter {
225
192
  const cacheBasePath = path.resolve(this._rootPath, ".cache");
226
193
  const cachePath = path.resolve(cacheBasePath, pkgVersion);
227
194
 
195
+
196
+ let prevProgressMessage = "";
228
197
  return {
229
198
  mode: watch ? "development" : "production",
230
199
  devtool: false,
@@ -425,14 +394,18 @@ export class SdCliServerBuilder extends EventEmitter {
425
394
  }
426
395
  return resultMessages.join(os.EOL);
427
396
  }
428
- })/*,
397
+ }),
429
398
  new webpack.ProgressPlugin({
430
399
  handler: (per: number, msg: string, ...args: string[]) => {
431
400
  const phaseText = msg ? ` - phase: ${msg}` : "";
432
401
  const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
433
- this._logger.debug(`Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`);
402
+ const progressMessage = `Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`;
403
+ if (progressMessage !== prevProgressMessage) {
404
+ prevProgressMessage = progressMessage;
405
+ this._logger.debug(progressMessage);
406
+ }
434
407
  }
435
- })*/
408
+ })
436
409
  ]
437
410
  };
438
411
  }
@@ -37,6 +37,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
37
37
  private readonly _npmConfigMap = new Map<string, INpmConfig>();
38
38
 
39
39
  private readonly _isAngular: boolean;
40
+ private readonly _hasAngularRoute: boolean;
40
41
 
41
42
  public constructor(private readonly _rootPath: string,
42
43
  private readonly _config: ISdCliLibPackageConfig,
@@ -52,6 +53,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
52
53
 
53
54
  // isAngular
54
55
  this._isAngular = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/core");
56
+ this._hasAngularRoute = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/router");
55
57
 
56
58
  // tsconfig
57
59
  this._tsconfigFilePath = path.resolve(this._rootPath, "tsconfig-build.json");
@@ -71,11 +73,11 @@ export class SdCliTsLibBuilder extends EventEmitter {
71
73
  "print-templates",
72
74
  "toasts",
73
75
  "AppPage"
74
- ], {
76
+ ], this._hasAngularRoute ? {
75
77
  glob: "**/*Page.ts",
76
78
  fileEndsWith: "Page",
77
79
  rootClassName: "AppPage"
78
- });
80
+ } : undefined);
79
81
  }
80
82
 
81
83
  // index 생성기 초기화
@@ -117,12 +119,21 @@ export class SdCliTsLibBuilder extends EventEmitter {
117
119
  const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
118
120
  if (changeFilePaths.length === 0) return;
119
121
 
120
- this._logger.debug("파일 변경 감지", changeInfos);
122
+ this._logger.debug("파일 변경 감지", changeFilePaths);
121
123
  this.emit("change");
122
124
 
123
125
  this._logger.debug("변경된 파일의 캐쉬 삭제...");
124
126
  for (const changeFilePath of changeFilePaths) {
125
- this._fileCache.delete(PathUtil.posix(changeFilePath));
127
+ const fileCache = this._fileCache.get(PathUtil.posix(changeFilePath));
128
+ if (fileCache) {
129
+ if (fileCache.importerSet) {
130
+ for (const importer of fileCache.importerSet.values()) {
131
+ this._fileCache.delete(importer);
132
+ }
133
+ }
134
+
135
+ this._fileCache.delete(PathUtil.posix(changeFilePath));
136
+ }
126
137
  }
127
138
 
128
139
  if (this._ngModuleGenerator) {
@@ -161,6 +172,10 @@ export class SdCliTsLibBuilder extends EventEmitter {
161
172
  this._logger.debug("린트...");
162
173
  buildResults.push(...await this._linter.lintAsync(relatedPaths, buildPack.program));
163
174
 
175
+ this._logger.debug("변경감지 대상목록 재구성...");
176
+ const watchRelatedPaths = await this.getAllRelatedPathsAsync();
177
+ watcher.add(watchRelatedPaths);
178
+
164
179
  this.emit("complete", buildResults);
165
180
  }
166
181
 
@@ -202,7 +217,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
202
217
  || (/node_modules[\\/]@simplysm[\\/]/).test(filePath)
203
218
  || workspaceRegex.test(filePath);
204
219
  });
205
- const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs|*.ts)");
220
+ const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs|*.ts|*.scss)");
206
221
  const mySourceFilePaths = await FsUtil.globAsync(mySourceGlobPath, {
207
222
  ignore: [
208
223
  "**/node_modules/**",
@@ -419,6 +434,7 @@ interface IFileCache {
419
434
  sourceFile?: ts.SourceFile;
420
435
  content?: string;
421
436
  styleContent?: string;
437
+ importerSet?: Set<string>;
422
438
  }
423
439
 
424
440
  interface ISdBuildPack {
package/src/commons.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export interface INpmConfig {
2
2
  name: string;
3
3
  version: string;
4
+ type?: "module";
4
5
  workspaces?: string[];
5
6
  main?: string;
6
7
  types?: string;
@@ -56,7 +57,6 @@ export interface ISdCliServerPackageConfig {
56
57
  env?: Record<string, string>;
57
58
  configs?: Record<string, any>;
58
59
  pm2?: Record<string, any> | boolean;
59
- iis?: { serverExeFilePath?: string } | boolean;
60
60
  externalNodeModules?: string[];
61
61
  publish?: TSdCliPublishConfig;
62
62
  }
@@ -107,4 +107,4 @@ export interface ISdCliClientPackageCordovaConfig {
107
107
  };
108
108
  }
109
109
 
110
- export type TSdCliCordovaPlatform = "browser" | "ios" | "android" | "windows";
110
+ export type TSdCliCordovaPlatform = "browser" | "ios" | "android" | "electron";
@@ -0,0 +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
+ }
@@ -14,7 +14,7 @@ export class SdCliLocalUpdate {
14
14
  if (!conf.localUpdates) return;
15
15
 
16
16
  const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
17
- this._logger.debug("로컬 업데이트 구성", updatePathInfos);
17
+ this._logger.debug("로컬 업데이트 구성");
18
18
 
19
19
  this._logger.log("로컬 라이브러리 업데이트 시작...");
20
20
  for (const updatePathInfo of updatePathInfos) {
@@ -37,7 +37,7 @@ export class SdCliLocalUpdate {
37
37
  if (!conf.localUpdates) return;
38
38
 
39
39
  const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
40
- this._logger.debug("로컬 업데이트 구성", updatePathInfos);
40
+ this._logger.debug("로컬 업데이트 구성");
41
41
 
42
42
  const watchPaths = (await updatePathInfos.mapManyAsync(async (item) => await this._getWatchPathsAsync(item.source))).distinct();
43
43
 
@@ -38,7 +38,7 @@ export class SdCliPrepare {
38
38
  if (node.hasChildPerformanceWarning) {
39
39
  node.parent.hasChildPerformanceWarning = true;
40
40
  }
41
- else if (usage.user + usage.system > 2000 * 1000 && node.kind !== 253) {
41
+ else if (usage.user + usage.system > 1000 * 1000 && node.kind !== 253) {
42
42
  error(node, {
43
43
  code: 9000,
44
44
  category: ts.DiagnosticCategory.Warning,
@@ -191,7 +191,7 @@ export class SdCliWorkspace {
191
191
  }
192
192
  catch (err) {
193
193
  this._loggingResults(totalResultMap);
194
- throw new err;
194
+ throw err;
195
195
  }
196
196
  }
197
197
 
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export * from "./builder/SdCliJsLibBuilder";
8
8
  export * from "./builder/SdCliServerBuilder";
9
9
  export * from "./builder/SdCliTsLibBuilder";
10
10
  export * from "./commons";
11
+ export * from "./entry-points/SdCliFileCrypto";
11
12
  export * from "./entry-points/SdCliLocalUpdate";
12
13
  export * from "./entry-points/SdCliNpm";
13
14
  export * from "./entry-points/SdCliPrepare";
@@ -16,9 +16,6 @@ import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
16
16
  import os from "os";
17
17
  import { INpmConfig } from "../commons";
18
18
 
19
- // TODO: 에러 메시지 처리
20
- // TODO: forRoot에 있는 Provider 처리??
21
- // TODO: CircularDependency
22
19
  export class SdCliNgModuleGenerator {
23
20
  private readonly _logger: Logger;
24
21
 
@@ -66,7 +63,7 @@ export class SdCliNgModuleGenerator {
66
63
  public async runAsync(): Promise<void> {
67
64
  this._logger.debug("Babel NgModule 정의 가져오기...");
68
65
  const bbNgModules = this._getBbNgModuleDefs();
69
-
66
+
70
67
  this._logger.debug("NgModule Preset 구성...");
71
68
  const tsPreset = this._getTsGenNgModulePreset();
72
69
 
@@ -441,9 +441,9 @@ export class SdCliBbFileMetadata {
441
441
  throw SdCliBbUtil.error("예상치 못한 방식의 코드가 발견되었습니다.", this.filePath, rawMeta);
442
442
  }
443
443
 
444
- private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata>();
444
+ private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata | undefined>();
445
445
 
446
- public getNgDecoArg(className: string): SdCliBbObjectMetadata {
446
+ public getNgDecoArg(className: string): SdCliBbObjectMetadata | undefined {
447
447
  if (this._getNgDecoArgCache.has(className)) {
448
448
  return this._getNgDecoArgCache.get(className)!;
449
449
  }
@@ -529,9 +529,9 @@ export class SdCliBbFileMetadata {
529
529
  }
530
530
  });
531
531
 
532
- if (result === undefined) {
533
- throw new NeverEntryError(this.filePath + "," + className);
534
- }
532
+ // if (result === undefined) {
533
+ // throw new NeverEntryError(this.filePath + "," + className);
534
+ // }
535
535
 
536
536
  this._getNgDecoArgCache.set(className, result);
537
537
  return result;
@@ -27,13 +27,13 @@ export class SdCliBbNgModuleMetadata {
27
27
 
28
28
  const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
29
29
 
30
- const expVal = argObjMeta.getPropValue("exports") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "exports");
30
+ const expVal = argObjMeta?.getPropValue("exports") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "exports");
31
31
  if (expVal !== undefined) {
32
32
  const expMetas = this._getExportAndProviderMetas(expVal);
33
33
  result.exports.push(...expMetas);
34
34
  }
35
35
 
36
- const provVal = argObjMeta.getPropValue("providers") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "providers");
36
+ const provVal = argObjMeta?.getPropValue("providers") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "providers");
37
37
  if (provVal !== undefined) {
38
38
  const provMetas = this._getExportAndProviderMetas(provVal);
39
39
  result.providers.push(...provMetas);
@@ -140,7 +140,7 @@ export class SdCliBbNgDirectiveMetadata {
140
140
  if (this._selectorCache !== undefined) return this._selectorCache;
141
141
 
142
142
  const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
143
- const val = argObjMeta.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵdir", "selector");
143
+ const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵdir", "selector");
144
144
  if (typeof val === "string") {
145
145
  this._selectorCache = val;
146
146
  return this._selectorCache;
@@ -162,7 +162,7 @@ export class SdCliBbNgComponentMetadata {
162
162
  if (this._selectorCache !== undefined) return this._selectorCache;
163
163
 
164
164
  const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
165
- const val = argObjMeta.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵcmp", "selector");
165
+ const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵcmp", "selector");
166
166
  if (typeof val === "string") {
167
167
  this._selectorCache = val;
168
168
  return this._selectorCache;
@@ -184,7 +184,7 @@ export class SdCliBbNgPipeMetadata {
184
184
  if (this._pipeNameCache !== undefined) return this._pipeNameCache;
185
185
 
186
186
  const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
187
- const val = argObjMeta.getPropValue("name") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵpipe", "name");
187
+ const val = argObjMeta?.getPropValue("name") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵpipe", "name");
188
188
  if (typeof val === "string") {
189
189
  this._pipeNameCache = val;
190
190
  return val;
@@ -59,6 +59,10 @@ export class SdCliBuildResultUtil {
59
59
 
60
60
 
61
61
  public static getMessage(result: ISdCliPackageBuildResult): string {
62
+ if (result.code === "ESLintError") {
63
+ return result.message;
64
+ }
65
+
62
66
  let str = "";
63
67
  if (result.filePath !== undefined) {
64
68
  str += `${result.filePath}(${result.line ?? 0}, ${result.char ?? 0}): `;