@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
@@ -5,10 +5,10 @@ import { NeverEntryError } from "@simplysm/sd-core-common";
5
5
  import { EventEmitter } from "events";
6
6
  import * as path from "path";
7
7
  import { SdTsDiagnosticUtil } from "../utils/SdTsDiagnosticUtil";
8
- import { ESLint } from "eslint";
8
+ import { ESLint, Linter } from "eslint";
9
9
  import { createHash } from "crypto";
10
10
  import { SdCliIndexFileGenerator } from "../build-tools/SdCliIndexFileGenerator";
11
- import { ParserOptions } from "@typescript-eslint/types";
11
+ import ParserOptions = Linter.ParserOptions;
12
12
 
13
13
  export class SdCliTypescriptBuilder extends EventEmitter {
14
14
  protected readonly _logger: Logger;
@@ -64,16 +64,17 @@ export class SdCliTypescriptBuilder extends EventEmitter {
64
64
 
65
65
  // 프로그램 리로드
66
66
  const buildResult: ISdPackageBuildResult[] = [];
67
- const buildDirtyFilePaths = await this.reloadProgramAsync(watch);
67
+ const reloadProgramResult = await this.reloadProgramAsync(watch);
68
+ buildResult.push(...reloadProgramResult.result);
68
69
 
69
70
  // 자동생성할 소스파일들 생성 및 리로드 (index.ts등)
70
- const buildGenAdditionalResult = await this.generateAdditionalFilesAsync(buildDirtyFilePaths, watch);
71
+ const buildGenAdditionalResult = await this.generateAdditionalFilesAsync(reloadProgramResult.dirtyFilePaths, watch);
71
72
  buildResult.push(...buildGenAdditionalResult.result);
72
- buildDirtyFilePaths.push(...buildGenAdditionalResult.dirtyFilePaths);
73
+ reloadProgramResult.dirtyFilePaths.push(...buildGenAdditionalResult.dirtyFilePaths);
73
74
 
74
75
  // 빌드시, 빌드 수행하고 종료
75
76
  if (!watch) {
76
- const buildDoAllResults = await this.doAllAsync(buildDirtyFilePaths.distinct());
77
+ const buildDoAllResults = await this.doAllAsync(reloadProgramResult.dirtyFilePaths.distinct());
77
78
  buildResult.push(...buildDoAllResults);
78
79
  this.emit("complete", buildResult.distinct());
79
80
  return;
@@ -98,14 +99,15 @@ export class SdCliTypescriptBuilder extends EventEmitter {
98
99
  this.emit("change");
99
100
 
100
101
  // 변경파일에 대한 프로그램 리로드
101
- const watchDirtyFilePaths = await this.reloadChangedProgramAsync(changedFilePaths, watch);
102
+ const reloadChangedProgramResult = await this.reloadChangedProgramAsync(changedFilePaths, watch);
103
+ const watchDirtyFilePaths = reloadChangedProgramResult.dirtyFilePaths;
102
104
  if (watchDirtyFilePaths.length === 0) {
103
105
  this.emit("complete", Array.from(resultMap.values()).mapMany());
104
106
  return;
105
107
  }
106
108
 
107
109
  // 변경파일에 대해 자동생성할 소스파일들 생성 및 리로드 (index.ts등)
108
- const watchGenAdditionalResult = await this.generateAdditionalFilesAsync(watchDirtyFilePaths, watch);
110
+ const watchGenAdditionalResult = await this.generateAdditionalFilesAsync([...changedFilePaths, ...watchDirtyFilePaths], watch);
109
111
  watchDirtyFilePaths.push(...watchGenAdditionalResult.dirtyFilePaths);
110
112
  watchDirtyFilePaths.distinctThis();
111
113
 
@@ -119,7 +121,7 @@ export class SdCliTypescriptBuilder extends EventEmitter {
119
121
  }
120
122
 
121
123
  // 결과 MAP 구성
122
- const result = [...watchGenAdditionalResult.result, ...watchDoAllResults].distinct();
124
+ const result = [...reloadChangedProgramResult.result, ...watchGenAdditionalResult.result, ...watchDoAllResults].distinct();
123
125
  for (const resultItem of result) {
124
126
  const posixFilePath = resultItem.filePath !== undefined ? PathUtil.posix(resultItem.filePath) : "undefined";
125
127
  const resultMapValue = resultMap.getOrCreate(posixFilePath, []);
@@ -146,7 +148,7 @@ export class SdCliTypescriptBuilder extends EventEmitter {
146
148
  // 변경감지용, 최초 빌드
147
149
 
148
150
  // 빌드 및 린트
149
- const buildDoAllResults = await this.doAllAsync(buildDirtyFilePaths.distinct());
151
+ const buildDoAllResults = await this.doAllAsync(reloadProgramResult.dirtyFilePaths.distinct());
150
152
  buildResult.push(...buildDoAllResults);
151
153
 
152
154
  // 결과 MAP 구성
@@ -173,7 +175,9 @@ export class SdCliTypescriptBuilder extends EventEmitter {
173
175
  const generateResult = await this._indexFileGenerator.generateAsync();
174
176
  result.result.push(...generateResult.result);
175
177
  if (generateResult.changed) {
176
- result.dirtyFilePaths = await this.reloadChangedProgramAsync([this._indexFileGenerator.indexFilePath], watch);
178
+ const reloadChangedProgramResult = await this.reloadChangedProgramAsync([this._indexFileGenerator.indexFilePath], watch);
179
+ result.dirtyFilePaths = reloadChangedProgramResult.dirtyFilePaths;
180
+ result.result.push(...reloadChangedProgramResult.result);
177
181
  }
178
182
  }
179
183
 
@@ -227,6 +231,7 @@ export class SdCliTypescriptBuilder extends EventEmitter {
227
231
  && PathUtil.isChildPath(item, this.rootPath)
228
232
  && FsUtil.exists(item)
229
233
  && !FsUtil.isDirectory(item)
234
+ && Boolean(this._program?.getSourceFiles().some((item1) => PathUtil.posix(item1.fileName) === PathUtil.posix(item)))
230
235
  && !await linter.isPathIgnored(item)
231
236
  ));
232
237
 
@@ -237,6 +242,7 @@ export class SdCliTypescriptBuilder extends EventEmitter {
237
242
  const severity: "warning" | "error" = msg.severity === 1 ? "warning" : "error";
238
243
 
239
244
  return {
245
+ type: "lint",
240
246
  filePath: report.filePath,
241
247
  severity,
242
248
  message: `${report.filePath}(${msg.line}, ${msg.column}): ${msg.ruleId ?? ""}: ${severity} ${msg.message}`
@@ -342,7 +348,7 @@ export class SdCliTypescriptBuilder extends EventEmitter {
342
348
  return result;
343
349
  }
344
350
 
345
- public async reloadChangedProgramAsync(changedFilePaths: string[], watch: boolean): Promise<string[]> {
351
+ public async reloadChangedProgramAsync(changedFilePaths: string[], watch: boolean): Promise<{ dirtyFilePaths: string[]; result: ISdPackageBuildResult[] }> {
346
352
  this._logger.debug("변경 프로그램 리로드", changedFilePaths);
347
353
 
348
354
  // 캐시 삭제
@@ -351,37 +357,59 @@ export class SdCliTypescriptBuilder extends EventEmitter {
351
357
  this._deleteFileCaches(changedFilePaths);
352
358
 
353
359
  // 프로그램 리로드
354
- const dirtyFilePaths = await this.reloadProgramAsync(watch);
360
+ const reloadProgramResult = await this.reloadProgramAsync(watch);
355
361
 
356
362
  // 변경사항 있을 경우, 변경감지중이면, 변경감지 경로 리로드
357
- if (dirtyFilePaths.length > 0 && watch) {
363
+ if (reloadProgramResult.dirtyFilePaths.length > 0 && watch) {
358
364
  this._reloadWatchPaths();
359
365
  }
360
366
 
361
367
  /*dirtyFilePaths.push(...changedFilePaths.filter((key) => this._fileCache.has(key)));
362
368
  dirtyFilePaths.distinctThis();*/
363
369
 
364
- this._logger.debug("변경 프로그램 리로드 결과", dirtyFilePaths);
365
- return dirtyFilePaths;
370
+ this._logger.debug("변경 프로그램 리로드 결과", reloadProgramResult.dirtyFilePaths);
371
+ return reloadProgramResult;
366
372
  }
367
373
 
368
- public async reloadProgramAsync(watch: boolean): Promise<string[]> {
369
- this._logger.debug("프로그램 리로드");
370
-
371
- const parsedTsconfig = ts.parseJsonConfigFileContent(this._tsconfig, ts.sys, this.rootPath);
372
-
373
- this._moduleResolutionCache = ts.createModuleResolutionCache(this.rootPath, (s) => s, parsedTsconfig.options);
374
- this._cacheCompilerHost = await this._createCacheCompilerHostAsync(parsedTsconfig, this._moduleResolutionCache);
374
+ public getParsedTsconfig(): ts.ParsedCommandLine {
375
+ return ts.parseJsonConfigFileContent(this._tsconfig, ts.sys, this.rootPath);
376
+ }
375
377
 
378
+ public configProgram(parsedTsconfig: ts.ParsedCommandLine): void {
376
379
  this._program = ts.createProgram(
377
380
  parsedTsconfig.fileNames,
378
381
  parsedTsconfig.options,
379
382
  this._cacheCompilerHost,
380
383
  this._program
381
384
  );
385
+ }
386
+
387
+ public getSemanticDiagnosticsOfNextAffectedFiles(): string[] | undefined {
388
+ const builder = this._builder as ts.SemanticDiagnosticsBuilderProgram;
389
+ const result = builder.getSemanticDiagnosticsOfNextAffectedFile();
390
+
391
+ if (result && "fileName" in result.affected) {
392
+ return [result.affected.fileName];
393
+ }
394
+ if (!result) {
395
+ return undefined;
396
+ }
397
+
398
+ return [];
399
+ }
400
+
401
+ public async reloadProgramAsync(watch: boolean): Promise<{ dirtyFilePaths: string[]; result: ISdPackageBuildResult[] }> {
402
+ this._logger.debug("프로그램 리로드");
403
+
404
+ const parsedTsconfig = this.getParsedTsconfig();
405
+
406
+ this._moduleResolutionCache = ts.createModuleResolutionCache(this.rootPath, (s) => s, parsedTsconfig.options);
407
+ this._cacheCompilerHost = await this._createCacheCompilerHostAsync(parsedTsconfig, this._moduleResolutionCache);
408
+
409
+ this.configProgram(parsedTsconfig);
382
410
 
383
- const baseGetSourceFiles = this._program.getSourceFiles;
384
- this._program.getSourceFiles = function (...parameters) {
411
+ const baseGetSourceFiles = this._program!.getSourceFiles;
412
+ this._program!.getSourceFiles = function (...parameters) {
385
413
  const files: readonly (ts.SourceFile & { version?: string })[] = baseGetSourceFiles(...parameters);
386
414
 
387
415
  for (const file of files) {
@@ -396,44 +424,67 @@ export class SdCliTypescriptBuilder extends EventEmitter {
396
424
  if (watch) {
397
425
  if (this.skipProcesses.includes("emit")) {
398
426
  this._builder = ts.createSemanticDiagnosticsBuilderProgram(
399
- this._program,
427
+ this._program!,
400
428
  this._cacheCompilerHost,
401
429
  this._builder as ts.SemanticDiagnosticsBuilderProgram
402
430
  );
403
431
  }
404
432
  else {
405
433
  this._builder = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
406
- this._program,
434
+ this._program!,
407
435
  this._cacheCompilerHost,
408
436
  this._builder as ts.EmitAndSemanticDiagnosticsBuilderProgram
409
437
  );
410
438
  }
411
- const builder = this._builder as ts.SemanticDiagnosticsBuilderProgram;
412
439
 
413
- const affectedFilePaths: string[] = [];
440
+ const buildResults: ISdPackageBuildResult[] = [];
441
+ let seq = 0;
442
+ const affectedFilePathSet = new Set<string>();
414
443
  while (true) {
415
- const result = builder.getSemanticDiagnosticsOfNextAffectedFile();
444
+ const prevUsage = process.cpuUsage();
445
+ if (process.env.SD_CLI_LOGGER_SEVERITY === "DEBUG") {
446
+ this._logger.debug(`프로그램 리로드 > 변경파일 목록구성: [SEQ: ${++seq}]`);
447
+ }
448
+
449
+ const affectedFilePaths = this.getSemanticDiagnosticsOfNextAffectedFiles();
416
450
 
417
- if (!result) break;
451
+ if (affectedFilePaths) {
452
+ if (affectedFilePaths.length > 0) {
453
+ const usage = process.cpuUsage(prevUsage);
418
454
 
419
- if ("fileName" in result.affected) {
420
- affectedFilePaths.push(result.affected.fileName);
455
+ if (usage.user + usage.system > 1000 * 1000) { // 1000ms
456
+ buildResults.push({
457
+ filePath: path.resolve(affectedFilePaths.last()!),
458
+ severity: "warning",
459
+ message: `${path.resolve(affectedFilePaths.last()!)}(0, 0): warning 소스코드 타입분석에 너무 많은 시간이 소요됩니다. (${Math.floor((usage.user + usage.system) / 1000).toLocaleString()}ms/cpu)`
460
+ });
461
+ }
462
+
463
+ affectedFilePathSet.adds(...affectedFilePaths.distinct());
464
+ }
465
+
466
+ if (process.env.SD_CLI_LOGGER_SEVERITY === "DEBUG") {
467
+ this._logger.debug(`프로그램 리로드 > 변경파일 목록구성: [SEQ: ${seq}, SIZE:${affectedFilePathSet.size}]\n` + affectedFilePaths.map((item) => "- " + item).join("\n"));
468
+ }
469
+ }
470
+ else {
471
+ break;
421
472
  }
422
473
  }
423
474
 
424
- const result = affectedFilePaths.distinct();
475
+ const dirtyFilePaths = Array.from(affectedFilePathSet.values());
425
476
 
426
- this._logger.debug("프로그램 리로드 결과", result);
477
+ this._logger.debug("프로그램 리로드 결과", dirtyFilePaths);
427
478
 
428
- return result;
479
+ return { dirtyFilePaths, result: buildResults };
429
480
  }
430
481
  else {
431
- this._builder = ts.createAbstractBuilder(this._program, this._cacheCompilerHost);
432
- const result = this._builder.getSourceFiles().map((item) => item.fileName).distinct();
482
+ this._builder = ts.createAbstractBuilder(this._program!, this._cacheCompilerHost);
483
+ const dirtyFilePaths = this._builder.getSourceFiles().map((item) => item.fileName).distinct();
433
484
 
434
- this._logger.debug("프로그램 리로드 결과", result);
485
+ this._logger.debug("프로그램 리로드 결과", dirtyFilePaths);
435
486
 
436
- return result;
487
+ return { dirtyFilePaths, result: [] };
437
488
  }
438
489
  }
439
490
 
package/src/commons.ts CHANGED
@@ -48,9 +48,13 @@ export interface INpmConfig {
48
48
  name: string;
49
49
  version: string;
50
50
  workspaces?: string[];
51
+ es2020?: string;
52
+ browser?: string;
53
+ module?: string;
51
54
  main?: string;
52
55
 
53
56
  dependencies?: Record<string, string>;
57
+ optionalDependencies?: Record<string, string>;
54
58
  devDependencies?: Record<string, string>;
55
59
  peerDependencies?: Record<string, string>;
56
60
  }
@@ -63,8 +67,10 @@ export interface ITsconfig {
63
67
  outDir?: string;
64
68
  declarationDir?: string;
65
69
  declaration?: boolean;
70
+ declarationMap?: boolean;
66
71
  baseUrl?: string;
67
72
  paths?: Record<string, string[]>;
73
+ generateTrace?: string;
68
74
  };
69
75
  angularCompilerOptions?: {
70
76
  enableI18nLegacyMessageIdFormat?: boolean;
@@ -73,6 +79,7 @@ export interface ITsconfig {
73
79
  strictTemplates?: boolean;
74
80
  strictInputTypes?: boolean;
75
81
  strictOutputEventTypes?: boolean;
82
+ enableIvy?: boolean;
76
83
  compilationMode?: "partial" | "full";
77
84
  disableTypeScriptVersionCheck?: boolean;
78
85
  };
@@ -34,7 +34,7 @@ export class SdCliProject {
34
34
  this.npmConfig = FsUtil.readJson(this.npmConfigFilePath);
35
35
  }
36
36
 
37
- public async buildAsync(opt: { watch?: boolean; packages?: string[]; options?: string[]; config?: string; skipProcesses?: string[]; localUpdate?: boolean }): Promise<{ hasError: boolean }> {
37
+ public async buildAsync(opt: { watch?: boolean; packages?: string[]; options?: string[]; config?: string; skipProcesses?: string[] }): Promise<{ hasError: boolean }> {
38
38
  this._logger.debug("프로젝트 설정 가져오기...");
39
39
  const config = await SdProjectConfigUtil.loadConfigAsync(
40
40
  this._rootPath,
@@ -43,13 +43,13 @@ export class SdCliProject {
43
43
  opt.config
44
44
  );
45
45
 
46
- if (opt.watch && opt.localUpdate && config.localUpdates) {
46
+ if (opt.watch && config.localUpdates) {
47
47
  this._logger.debug("로컬 라이브러리 업데이트 변경감지 시작...");
48
48
  await new SdCliLocalUpdater(this._rootPath).localUpdateAsync(true, opt);
49
49
  }
50
50
 
51
51
  this._logger.debug("프로젝트 패키지 목록 구성...");
52
- const allPkgs = await this._getAllPackagesAsync(config, opt.packages, opt.skipProcesses ?? [], !opt.localUpdate);
52
+ const allPkgs = await this._getAllPackagesAsync(config, opt.packages, opt.skipProcesses ?? []);
53
53
  const pkgs = allPkgs.filter((item) => !(item instanceof SdCliUnknownPackage)) as TSdCliBuildablePackage[];
54
54
 
55
55
  this._logger.debug("프로젝트 및 패키지 버전 설정...");
@@ -178,7 +178,7 @@ export class SdCliProject {
178
178
  );
179
179
 
180
180
  this._logger.debug("프로젝트 패키지 목록 구성...");
181
- const allPkgs = await this._getAllPackagesAsync(config, opt.packages, [], false);
181
+ const allPkgs = await this._getAllPackagesAsync(config, opt.packages, []);
182
182
  const pkgs = allPkgs.filter((item) => !(item instanceof SdCliUnknownPackage) && item.config.publish) as TSdCliBuildablePackage[];
183
183
 
184
184
  // 빌드가 필요하면 빌드함
@@ -186,8 +186,7 @@ export class SdCliProject {
186
186
  this._logger.debug("빌드 수행...");
187
187
  const buildResult = await this.buildAsync({
188
188
  watch: false,
189
- packages: pkgs.map((item) => item.npmConfig.name)
190
- .filter((item) => !opt.packages || opt.packages.includes(item)),
189
+ packages: opt.packages,
191
190
  options: opt.options,
192
191
  config: opt.config
193
192
  });
@@ -246,7 +245,7 @@ export class SdCliProject {
246
245
  }
247
246
  }
248
247
 
249
- private async _getAllPackagesAsync(config: ISdProjectConfig, packages: string[] | undefined, skipProcesses: string[], useCache: boolean): Promise<TSdCliPackage[]> {
248
+ private async _getAllPackagesAsync(config: ISdProjectConfig, packages: string[] | undefined, skipProcesses: string[]): Promise<TSdCliPackage[]> {
250
249
  // package.json에서 workspaces를 통해 패키지 경로 목록 가져오기
251
250
  const allPkgPaths = await this.npmConfig.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
252
251
  if (!allPkgPaths) {
@@ -298,10 +297,10 @@ export class SdCliProject {
298
297
  }
299
298
  else if (pkgInfo.config?.type === "client") {
300
299
  const serverPkgInfo = allPackageInfos.single((item) => item.name === (pkgInfo.config as ISdClientPackageConfig).server);
301
- pkgs.push(new SdCliClientPackage(pkgInfo.rootPath, pkgInfo.config, useCache, serverPkgInfo?.rootPath));
300
+ pkgs.push(new SdCliClientPackage(pkgInfo.rootPath, pkgInfo.config, skipProcesses as any, serverPkgInfo?.rootPath));
302
301
  }
303
302
  else if (pkgInfo.config?.type === "server") {
304
- pkgs.push(new SdCliServerPackage(pkgInfo.rootPath, pkgInfo.config, useCache));
303
+ pkgs.push(new SdCliServerPackage(pkgInfo.rootPath, pkgInfo.config, skipProcesses as any));
305
304
  }
306
305
  else {
307
306
  pkgs.push(new SdCliUnknownPackage(pkgInfo.rootPath));
@@ -315,6 +314,7 @@ export class SdCliProject {
315
314
  // 패키지의 의존성 패키지 중에 빌드해야할 패키지 목록에 이미 있는 의존성 패키지만 추리기
316
315
  const depNames = [
317
316
  ...Object.keys(pkg.npmConfig.dependencies ?? {}),
317
+ ...Object.keys(pkg.npmConfig.optionalDependencies ?? {}),
318
318
  ...Object.keys(pkg.npmConfig.devDependencies ?? {}),
319
319
  ...Object.keys(pkg.npmConfig.peerDependencies ?? {})
320
320
  ].distinct().filter((dep) => pkgNames.includes(dep));
@@ -367,6 +367,7 @@ export class SdCliProject {
367
367
  }
368
368
  };
369
369
  updateDepVersion(this.npmConfig.dependencies);
370
+ updateDepVersion(this.npmConfig.optionalDependencies);
370
371
  updateDepVersion(this.npmConfig.devDependencies);
371
372
  updateDepVersion(this.npmConfig.peerDependencies);
372
373
 
@@ -16,7 +16,7 @@ export class SdCliClientPackage extends SdCliPackageBase {
16
16
 
17
17
  public constructor(public readonly rootPath: string,
18
18
  public readonly config: ISdClientPackageConfig,
19
- public readonly useCache: boolean,
19
+ public readonly skipProcesses: ("lint" | "genNgModule")[],
20
20
  public readonly _serverPath?: string) {
21
21
  super(rootPath);
22
22
  }
@@ -25,7 +25,7 @@ export class SdCliClientPackage extends SdCliPackageBase {
25
25
  await this._genBuildTsconfigAsync();
26
26
 
27
27
  const buildTsconfigFilePath = path.resolve(this.rootPath, `sd-tsconfig.json`);
28
- const builder = new SdCliNgClientBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.useCache);
28
+ const builder = new SdCliNgClientBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.skipProcesses);
29
29
 
30
30
  await builder
31
31
  .on("change", () => {
@@ -41,7 +41,7 @@ export class SdCliClientPackage extends SdCliPackageBase {
41
41
  await this._genBuildTsconfigAsync();
42
42
 
43
43
  const buildTsconfigFilePath = path.resolve(this.rootPath, `sd-tsconfig.json`);
44
- const builder = new SdCliNgClientBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.useCache);
44
+ const builder = new SdCliNgClientBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.skipProcesses);
45
45
  return await builder
46
46
  .on("change", () => {
47
47
  this.emit("change", undefined);
@@ -72,14 +72,17 @@ export class SdCliClientPackage extends SdCliPackageBase {
72
72
  buildTsconfig.compilerOptions = buildTsconfig.compilerOptions ?? {};
73
73
  delete buildTsconfig.compilerOptions.baseUrl;
74
74
  delete buildTsconfig.compilerOptions.paths;
75
- buildTsconfig.compilerOptions.module = "es2020";
76
- buildTsconfig.compilerOptions.target = "es2015";
77
- buildTsconfig.compilerOptions.lib = ["es2015", "dom"];
78
- buildTsconfig.compilerOptions.outDir = `dist`;
79
- buildTsconfig.compilerOptions.declaration = false;
80
75
  delete buildTsconfig.compilerOptions.declarationDir;
76
+ buildTsconfig.compilerOptions = {
77
+ ...buildTsconfig.compilerOptions,
78
+ module: "es2020",
79
+ target: "es2015",
80
+ lib: ["es2015", "dom"],
81
+ outDir: "dist",
82
+ declaration: false,
83
+ baseUrl: this.rootPath
84
+ };
81
85
 
82
- buildTsconfig.compilerOptions.baseUrl = this.rootPath;
83
86
  buildTsconfig.angularCompilerOptions = {
84
87
  ...buildTsconfig.angularCompilerOptions ?? {},
85
88
  enableI18nLegacyMessageIdFormat: false,
@@ -91,6 +91,7 @@ export class SdCliLibraryPackage extends SdCliPackageBase {
91
91
  if (i === 0) {
92
92
  buildTsconfig.compilerOptions.declaration = true;
93
93
  buildTsconfig.compilerOptions.declarationDir = "dist-types";
94
+ buildTsconfig.compilerOptions.declarationMap = true;
94
95
  }
95
96
  else {
96
97
  buildTsconfig.compilerOptions.declaration = false;
@@ -25,6 +25,7 @@ export abstract class SdCliPackageBase extends EventEmitter {
25
25
  }
26
26
  };
27
27
  updateDepVersion(this.npmConfig.dependencies);
28
+ updateDepVersion(this.npmConfig.optionalDependencies);
28
29
  updateDepVersion(this.npmConfig.devDependencies);
29
30
  updateDepVersion(this.npmConfig.peerDependencies);
30
31
 
@@ -16,7 +16,7 @@ export class SdCliServerPackage extends SdCliPackageBase {
16
16
 
17
17
  public constructor(public readonly rootPath: string,
18
18
  public readonly config: ISdServerPackageConfig,
19
- public readonly useCache: boolean) {
19
+ public readonly skipProcesses: "lint"[]) {
20
20
  super(rootPath);
21
21
  }
22
22
 
@@ -24,7 +24,7 @@ export class SdCliServerPackage extends SdCliPackageBase {
24
24
  await this._genBuildTsconfigAsync();
25
25
 
26
26
  const buildTsconfigFilePath = path.resolve(this.rootPath, `sd-tsconfig.json`);
27
- const builder = new SdCliServerBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.useCache);
27
+ const builder = new SdCliServerBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.skipProcesses);
28
28
 
29
29
  await builder
30
30
  .on("change", () => {
@@ -51,7 +51,7 @@ export class SdCliServerPackage extends SdCliPackageBase {
51
51
  await this._genBuildTsconfigAsync();
52
52
 
53
53
  const buildTsconfigFilePath = path.resolve(this.rootPath, `sd-tsconfig.json`);
54
- const builder = new SdCliServerBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.useCache);
54
+ const builder = new SdCliServerBuilder(this.rootPath, buildTsconfigFilePath, process.cwd(), this.config, this.skipProcesses);
55
55
 
56
56
  await builder
57
57
  .on("change", () => {
@@ -47,8 +47,9 @@ export class SdWebpackUtil {
47
47
  result += err.message;
48
48
  }
49
49
  else {
50
- if (err.file !== undefined) {
51
- result += err.file.replace(/^\.\//, "");
50
+ const filePath = err.file ?? err.module?.nameForCondition();
51
+ if (filePath != null) {
52
+ result += filePath.replace(/^\.\//, "");
52
53
  if (err.loc !== undefined) {
53
54
  if ("start" in err.loc) {
54
55
  result += `(${err.loc.start.line}${err.loc.start.column !== undefined ? `, ${err.loc.start.column}` : ""})`;
@@ -35,22 +35,25 @@ try {
35
35
 
36
36
  if (!ngGenerator || !changedFilePaths) {
37
37
  ngGenerator = new SdCliNgLibraryBuilder(rootPath, tsconfigFilePath, ["emit", "check", "lint", "genIndex"], undefined);
38
- const genDirtyFilePaths = await ngGenerator.reloadProgramAsync(watch);
39
- const genResult = await ngGenerator.generateAdditionalFilesAsync(genDirtyFilePaths, watch);
38
+ const reloadProgramResult = await ngGenerator.reloadProgramAsync(watch);
39
+ const genResult = await ngGenerator.generateAdditionalFilesAsync(reloadProgramResult.dirtyFilePaths, watch);
40
40
  worker.send("complete", {
41
- dirtyFilePaths: [...genDirtyFilePaths, ...genResult.dirtyFilePaths],
42
- result: genResult.result
41
+ dirtyFilePaths: [...reloadProgramResult.dirtyFilePaths, ...genResult.dirtyFilePaths].distinct(),
42
+ result: [...reloadProgramResult.result, ...genResult.result].distinct()
43
43
  });
44
44
  }
45
45
  else {
46
- const genDirtyFilePaths = await ngGenerator.reloadChangedProgramAsync(changedFilePaths, watch);
47
- if (genDirtyFilePaths.length === 0) {
46
+ const reloadProgramResult = await ngGenerator.reloadChangedProgramAsync(changedFilePaths, watch);
47
+ if (reloadProgramResult.dirtyFilePaths.length === 0) {
48
48
  worker.send("complete", { dirtyFilePaths: [], result: [] });
49
49
  return;
50
50
  }
51
51
 
52
- const genResult = await ngGenerator.generateAdditionalFilesAsync(genDirtyFilePaths.distinct(), watch);
53
- worker.send("complete", { dirtyFilePaths: genResult.dirtyFilePaths, result: genResult.result });
52
+ const genResult = await ngGenerator.generateAdditionalFilesAsync(reloadProgramResult.dirtyFilePaths.distinct(), watch);
53
+ worker.send("complete", {
54
+ dirtyFilePaths: [...reloadProgramResult.dirtyFilePaths, ...genResult.dirtyFilePaths].distinct(),
55
+ result: [...reloadProgramResult.result, ...genResult.result].distinct()
56
+ });
54
57
  }
55
58
  });
56
59
  }