@simplysm/sd-cli 6.0.44 → 6.1.1

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 (93) hide show
  1. package/dist-node/bin/sd-cli.js +1 -6
  2. package/dist-node/bin/sd-cli.js.map +1 -1
  3. package/dist-node/builders/SdCliNgClientBuilder.js +104 -49
  4. package/dist-node/builders/SdCliNgClientBuilder.js.map +1 -1
  5. package/dist-node/builders/SdCliNgLibraryBuilder.js +26 -56
  6. package/dist-node/builders/SdCliNgLibraryBuilder.js.map +1 -1
  7. package/dist-node/builders/SdCliServerBuilder.js +118 -36
  8. package/dist-node/builders/SdCliServerBuilder.js.map +1 -1
  9. package/dist-node/builders/SdCliTypescriptBuilder.js +69 -27
  10. package/dist-node/builders/SdCliTypescriptBuilder.js.map +1 -1
  11. package/dist-node/entry-points/SdCliProject.js +9 -8
  12. package/dist-node/entry-points/SdCliProject.js.map +1 -1
  13. package/dist-node/packages/SdCliClientPackage.js +13 -10
  14. package/dist-node/packages/SdCliClientPackage.js.map +1 -1
  15. package/dist-node/packages/SdCliLibraryPackage.js +1 -0
  16. package/dist-node/packages/SdCliLibraryPackage.js.map +1 -1
  17. package/dist-node/packages/SdCliPackageBase.js +1 -0
  18. package/dist-node/packages/SdCliPackageBase.js.map +1 -1
  19. package/dist-node/packages/SdCliServerPackage.js +4 -4
  20. package/dist-node/packages/SdCliServerPackage.js.map +1 -1
  21. package/dist-node/utils/SdWebpackUtil.js +3 -2
  22. package/dist-node/utils/SdWebpackUtil.js.map +1 -1
  23. package/dist-node/workers/client-ng-gen-worker.js +11 -8
  24. package/dist-node/workers/client-ng-gen-worker.js.map +1 -1
  25. package/dist-types/bin/sd-cli.d.ts +1 -0
  26. package/dist-types/bin/sd-cli.d.ts.map +1 -0
  27. package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts +1 -0
  28. package/dist-types/build-tools/SdCliIndexFileGenerator.d.ts.map +1 -0
  29. package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts +1 -0
  30. package/dist-types/build-tools/SdCliNgModuleFilesGenerator.d.ts.map +1 -0
  31. package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts +1 -0
  32. package/dist-types/build-tools/metadata/SdAotMetadataReader.d.ts.map +1 -0
  33. package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts +1 -0
  34. package/dist-types/build-tools/metadata/SdIvyMetadataReader.d.ts.map +1 -0
  35. package/dist-types/build-tools/metadata/SdMetadataError.d.ts +1 -0
  36. package/dist-types/build-tools/metadata/SdMetadataError.d.ts.map +1 -0
  37. package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts +1 -0
  38. package/dist-types/build-tools/metadata/SdMyMetadataReader.d.ts.map +1 -0
  39. package/dist-types/builders/SdCliJavascriptLinter.d.ts +1 -0
  40. package/dist-types/builders/SdCliJavascriptLinter.d.ts.map +1 -0
  41. package/dist-types/builders/SdCliNgClientBuilder.d.ts +5 -2
  42. package/dist-types/builders/SdCliNgClientBuilder.d.ts.map +1 -0
  43. package/dist-types/builders/SdCliNgLibraryBuilder.d.ts +4 -1
  44. package/dist-types/builders/SdCliNgLibraryBuilder.d.ts.map +1 -0
  45. package/dist-types/builders/SdCliPublisher.d.ts +1 -0
  46. package/dist-types/builders/SdCliPublisher.d.ts.map +1 -0
  47. package/dist-types/builders/SdCliServerBuilder.d.ts +7 -3
  48. package/dist-types/builders/SdCliServerBuilder.d.ts.map +1 -0
  49. package/dist-types/builders/SdCliTypescriptBuilder.d.ts +12 -2
  50. package/dist-types/builders/SdCliTypescriptBuilder.d.ts.map +1 -0
  51. package/dist-types/commons.d.ts +8 -0
  52. package/dist-types/commons.d.ts.map +1 -0
  53. package/dist-types/entry-points/SdCliLocalUpdater.d.ts +1 -0
  54. package/dist-types/entry-points/SdCliLocalUpdater.d.ts.map +1 -0
  55. package/dist-types/entry-points/SdCliProject.d.ts +1 -1
  56. package/dist-types/entry-points/SdCliProject.d.ts.map +1 -0
  57. package/dist-types/packages/SdCliClientPackage.d.ts +3 -2
  58. package/dist-types/packages/SdCliClientPackage.d.ts.map +1 -0
  59. package/dist-types/packages/SdCliLibraryPackage.d.ts +1 -0
  60. package/dist-types/packages/SdCliLibraryPackage.d.ts.map +1 -0
  61. package/dist-types/packages/SdCliPackageBase.d.ts +1 -0
  62. package/dist-types/packages/SdCliPackageBase.d.ts.map +1 -0
  63. package/dist-types/packages/SdCliServerPackage.d.ts +3 -2
  64. package/dist-types/packages/SdCliServerPackage.d.ts.map +1 -0
  65. package/dist-types/packages/SdCliUnknownPackage.d.ts +1 -0
  66. package/dist-types/packages/SdCliUnknownPackage.d.ts.map +1 -0
  67. package/dist-types/utils/SdCliFileCrypto.d.ts +1 -0
  68. package/dist-types/utils/SdCliFileCrypto.d.ts.map +1 -0
  69. package/dist-types/utils/SdProjectConfigUtil.d.ts +1 -0
  70. package/dist-types/utils/SdProjectConfigUtil.d.ts.map +1 -0
  71. package/dist-types/utils/SdTsDiagnosticUtil.d.ts +1 -0
  72. package/dist-types/utils/SdTsDiagnosticUtil.d.ts.map +1 -0
  73. package/dist-types/utils/SdWebpackUtil.d.ts +1 -0
  74. package/dist-types/utils/SdWebpackUtil.d.ts.map +1 -0
  75. package/dist-types/workers/client-ng-gen-worker.d.ts +1 -0
  76. package/dist-types/workers/client-ng-gen-worker.d.ts.map +1 -0
  77. package/dist-types/workers/lib-build-worker.d.ts +1 -0
  78. package/dist-types/workers/lib-build-worker.d.ts.map +1 -0
  79. package/package.json +7 -7
  80. package/sd-tsconfig.node.json +2 -1
  81. package/src/bin/sd-cli.ts +1 -6
  82. package/src/builders/SdCliNgClientBuilder.ts +85 -61
  83. package/src/builders/SdCliNgLibraryBuilder.ts +28 -80
  84. package/src/builders/SdCliServerBuilder.ts +133 -43
  85. package/src/builders/SdCliTypescriptBuilder.ts +91 -40
  86. package/src/commons.ts +7 -0
  87. package/src/entry-points/SdCliProject.ts +10 -9
  88. package/src/packages/SdCliClientPackage.ts +12 -9
  89. package/src/packages/SdCliLibraryPackage.ts +1 -0
  90. package/src/packages/SdCliPackageBase.ts +1 -0
  91. package/src/packages/SdCliServerPackage.ts +3 -3
  92. package/src/utils/SdWebpackUtil.ts +3 -2
  93. package/src/workers/client-ng-gen-worker.ts +11 -8
@@ -13,7 +13,6 @@ import { NeverEntryError, StringUtil } from "@simplysm/sd-core-common";
13
13
  import { PathUtil } from "@simplysm/sd-core-node";
14
14
  import * as os from "os";
15
15
  import * as nodeSass from "node-sass";
16
- import { createHash } from "crypto";
17
16
  import { SdCliNgModuleFilesGenerator } from "../build-tools/SdCliNgModuleFilesGenerator";
18
17
  import { OptimizeFor } from "@angular/compiler-cli/src/ngtsc/typecheck/api";
19
18
  import { ModuleMetadata } from "@angular/compiler-cli/src/metadata/schema";
@@ -79,7 +78,6 @@ export class SdCliNgLibraryBuilder extends SdCliTypescriptBuilder {
79
78
 
80
79
  this._builder.emit(sourceFile, undefined, undefined, undefined, transformers);
81
80
 
82
- // TODO: sd-metadata를 ModuleMetadata로 만들게 아니고, 아예 IAotModuleDefMetadata형식으로 만들어지게 해야함
83
81
  if (this._program!.getCompilerOptions().declaration) {
84
82
  if (sourceFile.fileName.endsWith(".ts") && !sourceFile.fileName.endsWith(".d.ts")) {
85
83
  const metadata = this._getMetadata(sourceFile);
@@ -139,98 +137,46 @@ export class SdCliNgLibraryBuilder extends SdCliTypescriptBuilder {
139
137
  }
140
138
  }*/
141
139
 
142
- public override async reloadProgramAsync(watch: boolean): Promise<string[]> {
143
- this._logger.debug("프로그램 리로드");
144
-
145
- const parsedTsconfig = ts.parseJsonConfigFileContent(this._tsconfig, ts.sys, this.rootPath, this._tsconfig.angularCompilerOptions);
146
-
147
- this._moduleResolutionCache = ts.createModuleResolutionCache(this.rootPath, (s) => s, parsedTsconfig.options);
148
- this._cacheCompilerHost = await this._createCacheCompilerHostAsync(parsedTsconfig, this._moduleResolutionCache);
140
+ public override getParsedTsconfig(): ts.ParsedCommandLine {
141
+ return ts.parseJsonConfigFileContent(this._tsconfig, ts.sys, this.rootPath, this._tsconfig.angularCompilerOptions);
142
+ }
149
143
 
144
+ public override configProgram(parsedTsconfig: ts.ParsedCommandLine): void {
150
145
  this._ngProgram = new NgtscProgram(
151
146
  parsedTsconfig.fileNames,
152
147
  parsedTsconfig.options,
153
- this._cacheCompilerHost,
148
+ this._cacheCompilerHost!,
154
149
  this._ngProgram
155
150
  );
156
151
 
157
152
  this._ngCompiler = this._ngProgram.compiler;
158
153
  this._program = this._ngProgram.getTsProgram();
154
+ }
159
155
 
160
- const baseGetSourceFiles = this._program.getSourceFiles;
161
- this._program.getSourceFiles = function (...parameters) {
162
- const sourceFiles: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
163
-
164
- for (const sourceFile of sourceFiles) {
165
- if (sourceFile.version === undefined) {
166
- sourceFile.version = createHash("sha256").update(sourceFile.text).digest("hex");
167
- }
168
- }
169
-
170
- return sourceFiles;
171
- };
172
-
173
- if (watch) {
174
- if (this.skipProcesses.includes("emit")) {
175
- this._builder = ts.createSemanticDiagnosticsBuilderProgram(
176
- this._program,
177
- this._cacheCompilerHost,
178
- this._builder as ts.SemanticDiagnosticsBuilderProgram
179
- );
180
- }
181
- else {
182
- this._builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
183
- this._program,
184
- this._cacheCompilerHost,
185
- this._builder as ts.EmitAndSemanticDiagnosticsBuilderProgram
186
- );
187
- }
188
- const builder = this._builder as ts.SemanticDiagnosticsBuilderProgram;
189
-
190
- let seq = 0;
191
- const affectedFilePathSet = new Set<string>();
192
- while (true) {
193
- const affectedFilePaths: string[] = [];
194
- this._logger.debug(`프로그램 리로드 > 변경파일 목록구성: [SEQ: ${++seq}]`);
195
- const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
196
- if (this._ngCompiler!.ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith(".ngtypecheck.ts")) {
197
- const originalFilename = sourceFile.fileName.slice(0, -15) + ".ts";
198
- const originalSourceFile = builder.getSourceFile(originalFilename);
199
- if (originalSourceFile) {
200
- affectedFilePaths.push(originalSourceFile.fileName);
201
- }
202
- return true;
203
- }
204
- return false;
205
- });
206
-
207
- if (result && "fileName" in result.affected) {
208
- affectedFilePaths.push(result.affected.fileName);
156
+ public override getSemanticDiagnosticsOfNextAffectedFiles(): string[] | undefined {
157
+ const builder = this._builder as ts.SemanticDiagnosticsBuilderProgram;
158
+ const affectedFilePaths: string[] = [];
159
+ const result = builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
160
+ if (this._ngCompiler!.ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith(".ngtypecheck.ts")) {
161
+ const originalFilename = sourceFile.fileName.slice(0, -15) + ".ts";
162
+ const originalSourceFile = builder.getSourceFile(originalFilename);
163
+ if (originalSourceFile) {
164
+ affectedFilePaths.push(originalSourceFile.fileName);
209
165
  }
210
-
211
- affectedFilePaths.distinctThis();
212
-
213
- this._logger.debug(`프로그램 리로드 > 변경파일 목록구성: [SEQ: ${seq}, SIZE:${affectedFilePathSet.size}]\n` + affectedFilePaths.map((item) => "- " + item).join("\n"));
214
-
215
- affectedFilePathSet.adds(...affectedFilePaths.distinct());
216
-
217
- if (!result) break;
166
+ return true;
218
167
  }
168
+ return false;
169
+ });
219
170
 
220
- const result = Array.from(affectedFilePathSet.values());
221
-
222
- this._logger.debug("프로그램 리로드", result);
223
-
224
- return result;
171
+ if (result && "fileName" in result.affected) {
172
+ affectedFilePaths.push(result.affected.fileName);
173
+ return affectedFilePaths.distinct();
225
174
  }
226
- else {
227
- this._builder = ts.createAbstractBuilder(this._program, this._cacheCompilerHost);
228
- const result = this._builder.getSourceFiles().map((item) => item.fileName).distinct();
229
-
230
- this._logger.debug("프로그램 리로드", result);
231
-
232
- return result;
175
+ if (!result) {
176
+ return undefined;
233
177
  }
178
+
179
+ return [];
234
180
  }
235
181
 
236
182
  protected override _deleteFileCaches(filePaths: string[]): void {
@@ -286,7 +232,9 @@ export class SdCliNgLibraryBuilder extends SdCliTypescriptBuilder {
286
232
  const generateResult = await this._moduleFilesGenerator.generateAsync();
287
233
  result.result.push(...generateResult.result);
288
234
  if (generateResult.changedFilePaths.length > 0) {
289
- result.dirtyFilePaths = await this.reloadChangedProgramAsync(generateResult.changedFilePaths, watch);
235
+ const reloadChangedProgramResult = await this.reloadChangedProgramAsync(generateResult.changedFilePaths, watch);
236
+ result.dirtyFilePaths = reloadChangedProgramResult.dirtyFilePaths;
237
+ result.result.push(...reloadChangedProgramResult.result);
290
238
  }
291
239
 
292
240
  this._logger.debug("Angular Module, RoutingModule 생성 결과", result);
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from "events";
2
2
  import { INpmConfig, ISdPackageBuildResult, ISdServerPackageConfig, ITsconfig } from "../commons";
3
3
  import * as ts from "typescript";
4
- import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
4
+ import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
5
5
  import { ObjectUtil, StringUtil, Wait } from "@simplysm/sd-core-common";
6
6
  import * as webpack from "webpack";
7
7
  import * as path from "path";
@@ -24,16 +24,21 @@ export class SdCliServerBuilder extends EventEmitter {
24
24
  public npmConfigCache = new Map<string, INpmConfig>();
25
25
  private _server?: SdServiceServer;
26
26
 
27
+ protected readonly _logger: Logger;
28
+
27
29
  public constructor(public rootPath: string,
28
30
  public tsconfigFilePath: string,
29
31
  public projectRootPath: string,
30
32
  public config: ISdServerPackageConfig,
31
- public useCache: boolean) {
33
+ public skipProcesses: "lint"[]) {
32
34
  super();
33
35
 
34
36
  const tsconfig: ITsconfig = FsUtil.readJson(this.tsconfigFilePath);
35
37
  this.parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this.rootPath);
36
- this.npmConfigCache.set(this.rootPath, FsUtil.readJson(path.resolve(this.rootPath, "package.json")));
38
+ const npmConfig = FsUtil.readJson(path.resolve(this.rootPath, "package.json"));
39
+ this.npmConfigCache.set(this.rootPath, npmConfig);
40
+
41
+ this._logger = Logger.get(["simplysm", "sd-cli", this.constructor.name, npmConfig.name]);
37
42
  }
38
43
 
39
44
  public on(event: "change", listener: () => void): this;
@@ -47,10 +52,10 @@ export class SdCliServerBuilder extends EventEmitter {
47
52
 
48
53
  await FsUtil.removeAsync(this.parsedTsconfig.options.outDir!);
49
54
 
50
- const externalModuleNames = this._findExternalModuleNames(false);
51
-
52
- // 빌드
55
+ const externalModuleNames = this._findExternalModules(false).map((item) => item.name);
53
56
 
57
+ // WEBPACK 빌드
58
+ this._logger.debug("Webpack 빌드 수행");
54
59
  const webpackConfig = this._getWebpackConfig(false, externalModuleNames);
55
60
  const compiler = webpack(webpackConfig);
56
61
  const buildResults = await new Promise<ISdPackageBuildResult[]>((resolve, reject) => {
@@ -66,6 +71,7 @@ export class SdCliServerBuilder extends EventEmitter {
66
71
  resolve(results);
67
72
  });
68
73
  });
74
+ this._logger.debug("Webpack 빌드 결과", buildResults);
69
75
 
70
76
  // .config.json 파일 쓰기
71
77
 
@@ -139,6 +145,7 @@ export class SdCliServerBuilder extends EventEmitter {
139
145
  for (const externalModuleName of externalModuleNames) {
140
146
  distNpmConfig.dependencies[externalModuleName] = "*";
141
147
  }
148
+ delete distNpmConfig.optionalDependencies;
142
149
  delete distNpmConfig.devDependencies;
143
150
  delete distNpmConfig.peerDependencies;
144
151
 
@@ -150,7 +157,9 @@ export class SdCliServerBuilder extends EventEmitter {
150
157
  public async watchAsync(): Promise<void> {
151
158
  await FsUtil.removeAsync(this.parsedTsconfig.options.outDir!);
152
159
 
153
- const externalModuleNames = this._findExternalModuleNames(true);
160
+ const externalModules = this._findExternalModules(true);
161
+ const externalModuleNames = externalModules.map((item) => item.name);
162
+ const externalModulePaths = externalModules.map((item) => item.path);
154
163
 
155
164
  // 빌드
156
165
  const webpackConfig = this._getWebpackConfig(true, externalModuleNames);
@@ -160,6 +169,8 @@ export class SdCliServerBuilder extends EventEmitter {
160
169
  this.emit("change");
161
170
  callback();
162
171
 
172
+ this._logger.debug("Webpack 빌드 수행");
173
+
163
174
  await this._stopServerAsync();
164
175
  });
165
176
 
@@ -198,9 +209,73 @@ export class SdCliServerBuilder extends EventEmitter {
198
209
  // 결과 리턴
199
210
 
200
211
  this.emit("complete", results, this._server);
212
+ this._logger.debug("Webpack 빌드 수행 결과", results);
201
213
  resolve();
202
214
  });
203
215
  });
216
+
217
+ // external 변경에 따른 서버 재시작을 위한 WATCH 구성
218
+
219
+ const getWatchPathsAsync = async (): Promise<string[]> => {
220
+ const result: string[] = [];
221
+ for (const modulePath of externalModulePaths) {
222
+ const npmConfig = this._getNpmConfig(modulePath);
223
+ if (!npmConfig) continue;
224
+ const distPath = path.resolve(modulePath, path.dirname(npmConfig.es2020 ?? npmConfig.module ?? npmConfig.main ?? "dist"));
225
+ const watchPaths = (await FsUtil.globAsync(path.resolve(distPath, "**")))
226
+ .filter((item) => (
227
+ item.includes("@simplysm")
228
+ && FsUtil.exists(item)
229
+ && FsUtil.isDirectory(item)
230
+ ));
231
+
232
+ result.push(...watchPaths);
233
+ }
234
+
235
+ return result;
236
+ };
237
+
238
+ const watchPaths = await getWatchPathsAsync();
239
+ const watcher = new SdFsWatcher();
240
+ watcher
241
+ .onChange(async (changeInfos) => {
242
+ const dirtyFilePaths = changeInfos
243
+ .map((changeInfo) => changeInfo.filePath)
244
+ .filter((item) => path.basename(item).includes("."))
245
+ .distinct();
246
+
247
+ if (dirtyFilePaths.length === 0) return;
248
+
249
+ this.emit("change");
250
+ this._logger.debug("서버 재시작");
251
+
252
+ const watchPaths2 = await getWatchPathsAsync();
253
+ watcher.replaceWatchPaths(watchPaths2);
254
+
255
+ await this._stopServerAsync();
256
+
257
+ const results: ISdPackageBuildResult[] = [];
258
+
259
+ try {
260
+ await this._startServerAsync();
261
+ }
262
+ catch (error) {
263
+ if (error instanceof Error) {
264
+ results.push({
265
+ filePath: undefined,
266
+ severity: "error",
267
+ message: error.message
268
+ });
269
+ }
270
+ else {
271
+ throw error;
272
+ }
273
+ }
274
+
275
+ this.emit("complete", results, this._server);
276
+ this._logger.debug("서버 재시작 결과", results);
277
+ })
278
+ .watch(watchPaths);
204
279
  }
205
280
 
206
281
  private async _stopServerAsync(): Promise<void> {
@@ -241,10 +316,11 @@ export class SdCliServerBuilder extends EventEmitter {
241
316
  target: ["node", "es2020"],
242
317
  profile: false,
243
318
  resolve: {
319
+ roots: [this.rootPath],
244
320
  extensions: [".ts", ".tsx", ".js"],
245
321
  symlinks: true,
246
322
  // modules: [this.projectRootPath, "node_modules"],
247
- mainFields: ["es2020", "main", "module"]
323
+ mainFields: ["es2020", "module", "main"]
248
324
  },
249
325
  /*resolveLoader: {
250
326
  symlinks: true,
@@ -256,7 +332,6 @@ export class SdCliServerBuilder extends EventEmitter {
256
332
  context: this.projectRootPath,
257
333
  entry: {
258
334
  main: [
259
- // TODO: "source-map-support/register"??
260
335
  path.resolve(this.rootPath, "src/main.ts")
261
336
  ]
262
337
  },
@@ -303,7 +378,15 @@ export class SdCliServerBuilder extends EventEmitter {
303
378
  }
304
379
  ]
305
380
  },
306
- cache: (watch && this.useCache) ? { type: "memory", maxGenerations: 1 } : false,
381
+ ...watch ? {
382
+ cache: { type: "memory", maxGenerations: 1 },
383
+ snapshot: {
384
+ immutablePaths: this._findAllInternalModuleCachePaths(),
385
+ managedPaths: this._findAllInternalModuleCachePaths()
386
+ }
387
+ } : {
388
+ cache: false
389
+ },
307
390
  optimization: {
308
391
  minimizer: watch ? [] : [
309
392
  new JavaScriptOptimizerPlugin({
@@ -351,41 +434,47 @@ export class SdCliServerBuilder extends EventEmitter {
351
434
  SD_VERSION: this._getNpmConfig(this.rootPath)!.version,
352
435
  ...this.config.env
353
436
  }),
354
- new ESLintWebpackPlugin({
355
- context: this.rootPath,
356
- eslintPath: path.resolve(this.projectRootPath, "node_modules", "eslint"),
357
- extensions: ["js", "ts"],
358
- exclude: ["node_modules"],
359
- fix: false,
360
- threads: true,
361
- formatter: (results: LintResult[]) => {
362
- const resultMessages: string[] = [];
363
- for (const result of results) {
364
- for (const msg of result.messages) {
365
- resultMessages.push(`${result.filePath}(${msg.line}, ${msg.column}): ${msg.ruleId ?? ""}: ${msg.severity === 1 ? "warning" : msg.severity === 2 ? "error" : ""} ${msg.message}`);
437
+ ...!this.skipProcesses.includes("lint") ? [
438
+ new ESLintWebpackPlugin({
439
+ context: this.rootPath,
440
+ eslintPath: path.resolve(this.projectRootPath, "node_modules", "eslint"),
441
+ extensions: ["js", "ts"],
442
+ exclude: ["node_modules"],
443
+ fix: false,
444
+ threads: true,
445
+ formatter: (results: LintResult[]) => {
446
+ const resultMessages: string[] = [];
447
+ for (const result of results) {
448
+ for (const msg of result.messages) {
449
+ resultMessages.push(`${result.filePath}(${msg.line}, ${msg.column}): ${msg.ruleId ?? ""}: ${msg.severity === 1 ? "warning" : msg.severity === 2 ? "error" : ""} ${msg.message}`);
450
+ }
366
451
  }
452
+ return resultMessages.join(os.EOL);
367
453
  }
368
- return resultMessages.join(os.EOL);
454
+ })
455
+ ] : [],
456
+ new webpack.ProgressPlugin({
457
+ handler: (per: number, msg: string, ...args: string[]) => {
458
+ const phaseText = msg ? ` - phase: ${msg}` : "";
459
+ const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
460
+ this._logger.debug(`Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`);
369
461
  }
370
462
  })
371
463
  ],
372
464
  node: false,
373
- externals: [
374
- ...externalModuleNames,
375
- ...this.config.externalDependencies ? this.config.externalDependencies : []
376
- ].distinct(),
465
+ externals: externalModuleNames,
377
466
  stats: "errors-warnings"
378
467
  };
379
468
  }
380
469
 
381
- /*private _findAllInternalModuleCachePaths(): string[] {
470
+ private _findAllInternalModuleCachePaths(): string[] {
382
471
  return this._findAllNodeModules(this.rootPath, this.projectRootPath)
383
472
  .mapMany((item) => (
384
473
  FsUtil.readdir(item)
385
- .filter((item1) => !item1.startsWith("@simplysm"))
474
+ .filter((item1) => item1 !== "@simplysm")
386
475
  .map((item1) => path.resolve(item, item1))
387
476
  ));
388
- }*/
477
+ }
389
478
 
390
479
  private _findAllNodeModules(from: string, root: string): string[] {
391
480
  const nodeModules: string[] = [];
@@ -420,27 +509,28 @@ export class SdCliServerBuilder extends EventEmitter {
420
509
  return undefined;
421
510
  }
422
511
 
423
- private _findExternalModuleNames(all: boolean): string[] {
512
+ private _findExternalModules(all: boolean): { name: string; path: string }[] {
424
513
  const loadedModuleNames: string[] = [];
425
- const externalModuleNames: string[] = [];
514
+ const externalModules: { name: string; path: string }[] = [];
426
515
 
427
- const fn = (rootPath: string): void => {
428
- const npmConfig = this._getNpmConfig(rootPath);
516
+ const fn = (currPath: string): void => {
517
+ const npmConfig = this._getNpmConfig(currPath);
429
518
  if (!npmConfig) return;
430
519
 
431
- for (const moduleName of Object.keys(npmConfig.dependencies ?? {})) {
520
+ for (const moduleName of Object.keys({
521
+ ...npmConfig.dependencies,
522
+ ...npmConfig.optionalDependencies
523
+ })) {
432
524
  if (loadedModuleNames.includes(moduleName)) continue;
433
525
  loadedModuleNames.push(moduleName);
434
526
 
435
- if (this.config.externalDependencies?.includes(moduleName)) {
436
- externalModuleNames.push(moduleName);
437
- }
438
-
439
- const modulePath = this._findModulePath(moduleName, rootPath);
527
+ const modulePath = this._findModulePath(moduleName, currPath);
440
528
  if (StringUtil.isNullOrEmpty(modulePath)) continue;
441
529
 
442
- if (all || FsUtil.exists(path.resolve(modulePath, "binding.gyp"))) {
443
- externalModuleNames.push(moduleName);
530
+ if (all
531
+ || this.config.externalDependencies?.includes(moduleName)
532
+ || FsUtil.exists(path.resolve(modulePath, "binding.gyp"))) {
533
+ externalModules.push({ path: modulePath, name: moduleName });
444
534
  }
445
535
 
446
536
  fn(modulePath);
@@ -449,7 +539,7 @@ export class SdCliServerBuilder extends EventEmitter {
449
539
 
450
540
  fn(this.rootPath);
451
541
 
452
- return externalModuleNames.distinct();
542
+ return externalModules.distinct();
453
543
  }
454
544
 
455
545
  private _getNpmConfig(rootPath: string): INpmConfig | undefined {