@simplysm/sd-cli 12.8.21 → 12.9.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 (96) hide show
  1. package/dist/entry/sd-cli-ai-command.js +2 -1
  2. package/dist/entry/sd-cli-ai-command.js.map +1 -1
  3. package/dist/entry/sd-cli-cordova.d.ts +1 -1
  4. package/dist/entry/sd-cli-cordova.js +10 -9
  5. package/dist/entry/sd-cli-cordova.js.map +1 -1
  6. package/dist/entry/sd-cli-electron.d.ts +6 -6
  7. package/dist/entry/sd-cli-electron.js +15 -9
  8. package/dist/entry/sd-cli-electron.js.map +1 -1
  9. package/dist/entry/sd-cli-local-update.d.ts +5 -5
  10. package/dist/entry/sd-cli-local-update.js +8 -12
  11. package/dist/entry/sd-cli-local-update.js.map +1 -1
  12. package/dist/entry/sd-cli-project.d.ts +11 -11
  13. package/dist/entry/sd-cli-project.js +11 -14
  14. package/dist/entry/sd-cli-project.js.map +1 -1
  15. package/dist/entry/utils/loadProjConfAsync.d.ts +5 -0
  16. package/dist/entry/utils/loadProjConfAsync.js +8 -0
  17. package/dist/entry/utils/loadProjConfAsync.js.map +1 -0
  18. package/dist/pkg-builders/client/sd-client.build-runner.js +1 -1
  19. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  20. package/dist/pkg-builders/client/sd-ng.bundler-context.d.ts +6 -5
  21. package/dist/pkg-builders/client/sd-ng.bundler-context.js +6 -6
  22. package/dist/pkg-builders/client/sd-ng.bundler-context.js.map +1 -1
  23. package/dist/pkg-builders/client/sd-ng.bundler.d.ts +13 -13
  24. package/dist/pkg-builders/client/sd-ng.bundler.js +1 -1
  25. package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
  26. package/dist/pkg-builders/client/sd-ng.plugin-creator.js +4 -88
  27. package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
  28. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js.map +1 -1
  29. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.d.ts +1 -1
  30. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
  31. package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
  32. package/dist/pkg-builders/sd-multi.build-runner.d.ts +4 -0
  33. package/dist/pkg-builders/sd-multi.build-runner.js +33 -25
  34. package/dist/pkg-builders/sd-multi.build-runner.js.map +1 -1
  35. package/dist/pkg-builders/server/sd-server.build-runner.js.map +1 -1
  36. package/dist/pkg-builders/server/sd-server.bundler.d.ts +6 -2
  37. package/dist/pkg-builders/server/sd-server.bundler.js +24 -24
  38. package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
  39. package/dist/sd-cli/vitest.config.d.ts +2 -0
  40. package/dist/sd-cli/vitest.config.js +15 -0
  41. package/dist/sd-cli/vitest.config.js.map +1 -0
  42. package/dist/sd-cli.js +7 -36
  43. package/dist/sd-cli.js.map +1 -1
  44. package/dist/ts-compiler/sd-dependency-analyzer.d.ts +8 -0
  45. package/dist/ts-compiler/sd-dependency-analyzer.js +244 -0
  46. package/dist/ts-compiler/sd-dependency-analyzer.js.map +1 -0
  47. package/dist/ts-compiler/sd-dependency-cache.d.ts +27 -0
  48. package/dist/ts-compiler/sd-dependency-cache.js +232 -0
  49. package/dist/ts-compiler/sd-dependency-cache.js.map +1 -0
  50. package/dist/ts-compiler/sd-ts-compiler.d.ts +7 -9
  51. package/dist/ts-compiler/sd-ts-compiler.js +101 -188
  52. package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
  53. package/dist/types/worker.types.d.ts +19 -0
  54. package/dist/utils/sd-cli-performance-time.d.ts +2 -1
  55. package/dist/utils/sd-cli-performance-time.js +9 -9
  56. package/dist/utils/sd-cli-performance-time.js.map +1 -1
  57. package/dist/workers/style-bundler.worker.d.ts +1 -0
  58. package/dist/workers/style-bundler.worker.js +56 -0
  59. package/dist/workers/style-bundler.worker.js.map +1 -0
  60. package/package.json +11 -11
  61. package/src/entry/sd-cli-ai-command.ts +2 -1
  62. package/src/entry/sd-cli-cordova.ts +20 -20
  63. package/src/entry/sd-cli-electron.ts +54 -23
  64. package/src/entry/sd-cli-local-update.ts +14 -29
  65. package/src/entry/sd-cli-project.ts +24 -41
  66. package/src/entry/utils/loadProjConfAsync.ts +12 -0
  67. package/src/pkg-builders/client/sd-client.build-runner.ts +7 -7
  68. package/src/pkg-builders/client/sd-ng.bundler-context.ts +15 -12
  69. package/src/pkg-builders/client/sd-ng.bundler.ts +17 -20
  70. package/src/pkg-builders/client/sd-ng.plugin-creator.ts +5 -94
  71. package/src/pkg-builders/lib/sd-js-lib.build-runner.ts +6 -6
  72. package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +7 -7
  73. package/src/pkg-builders/lib/sd-ts-lib.builder.ts +1 -1
  74. package/src/pkg-builders/sd-multi.build-runner.ts +54 -39
  75. package/src/pkg-builders/server/sd-server.build-runner.ts +6 -6
  76. package/src/pkg-builders/server/sd-server.bundler.ts +43 -35
  77. package/src/sd-cli.ts +7 -36
  78. package/src/ts-compiler/sd-dependency-analyzer.ts +312 -0
  79. package/src/ts-compiler/sd-dependency-cache.ts +328 -0
  80. package/src/ts-compiler/sd-ts-compiler.ts +161 -256
  81. package/src/types/worker.types.ts +17 -0
  82. package/src/utils/sd-cli-performance-time.ts +9 -9
  83. package/src/workers/style-bundler.worker.ts +70 -0
  84. package/tests/deps/sd-dependency-analyzer.spec.ts +272 -0
  85. package/tests/deps/sd-dependency-cache.spec.ts +144 -0
  86. package/tsconfig.json +1 -1
  87. package/tsconfig.test.json +8 -0
  88. package/vitest.config.ts +15 -0
  89. package/dist/index.d.ts +0 -34
  90. package/dist/index.js +0 -35
  91. package/dist/index.js.map +0 -1
  92. package/dist/ts-compiler/sd-ts-dependency-analyzer.d.ts +0 -10
  93. package/dist/ts-compiler/sd-ts-dependency-analyzer.js +0 -140
  94. package/dist/ts-compiler/sd-ts-dependency-analyzer.js.map +0 -1
  95. package/src/index.ts +0 -34
  96. package/src/ts-compiler/sd-ts-dependency-analyzer.ts +0 -176
@@ -1,14 +1,9 @@
1
1
  import ts from "typescript";
2
2
  import path from "path";
3
- import { FsUtils, PathUtils, SdLogger, TNormPath } from "@simplysm/sd-core-node";
3
+ import { FsUtils, PathUtils, SdLogger, SdWorker, TNormPath } from "@simplysm/sd-core-node";
4
4
  import { StringUtils } from "@simplysm/sd-core-common";
5
5
  import { NgtscProgram, OptimizeFor } from "@angular/compiler-cli";
6
- import {
7
- ComponentStylesheetBundler,
8
- } from "@angular/build/src/tools/esbuild/angular/component-stylesheets";
9
6
  import { AngularCompilerHost } from "@angular/build/src/tools/angular/angular-host";
10
- import { transformSupportedBrowsersToTargets } from "@angular/build/src/tools/esbuild/utils";
11
- import browserslist from "browserslist";
12
7
  import {
13
8
  replaceBootstrap,
14
9
  } from "@angular/build/src/tools/angular/transformers/jit-bootstrap-transformer";
@@ -19,19 +14,26 @@ import {
19
14
  SdTsCompilerOptions,
20
15
  TStylesheetBundlingResult,
21
16
  } from "../types/ts-compiler.types";
22
- import { ISdBuildMessage } from "../types/build.types";
23
17
  import {
24
18
  createWorkerTransformer,
25
19
  } from "@angular/build/src/tools/angular/transformers/web-worker-transformer";
26
20
  import { ESLint } from "eslint";
27
- import { SdTsDependencyAnalyzer } from "./sd-ts-dependency-analyzer";
21
+ import { ISdAffectedFileTreeNode, SdDependencyCache } from "./sd-dependency-cache";
22
+ import { SdDependencyAnalyzer } from "./sd-dependency-analyzer";
23
+ import { TStyleBundlerWorkerType } from "../types/worker.types";
28
24
 
29
25
  export class SdTsCompiler {
30
26
  private _logger = SdLogger.get(["simplysm", "sd-cli", "SdTsCompiler"]);
31
27
 
32
28
  private _isForAngular: boolean;
33
29
 
34
- private _revDepCacheMap = new Map<TNormPath, Set<TNormPath>>();
30
+ private _stylesheetBundlingWorker?: SdWorker<TStyleBundlerWorkerType>;
31
+
32
+ private _ngProgram: NgtscProgram | undefined;
33
+ private _program: ts.Program | undefined;
34
+
35
+ // 빌드정보 캐싱
36
+ private _depCache = new SdDependencyCache();
35
37
  private _sourceFileCacheMap = new Map<TNormPath, ts.SourceFile>();
36
38
  private _emittedFilesCacheMap = new Map<
37
39
  TNormPath,
@@ -41,15 +43,7 @@ export class SdTsCompiler {
41
43
  }[]
42
44
  >();
43
45
 
44
- private _stylesheetBundler: ComponentStylesheetBundler | undefined;
45
-
46
- private _ngProgram: NgtscProgram | undefined;
47
- private _program: ts.Program | undefined;
48
-
49
- private _modifiedFileSet = new Set<TNormPath>();
50
- private _affectedFileSet = new Set<TNormPath>();
51
-
52
- private _watchFileSet = new Set<TNormPath>();
46
+ // 빌드결과 캐싱
53
47
  private _stylesheetBundlingResultMap = new Map<TNormPath, TStylesheetBundlingResult>();
54
48
 
55
49
  private _perf!: SdCliPerformanceTimer;
@@ -60,46 +54,9 @@ export class SdTsCompiler {
60
54
  const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
61
55
  const tsconfig = FsUtils.readJson(tsconfigPath);
62
56
  this._isForAngular = Boolean(tsconfig.angularCompilerOptions);
63
-
64
- if (this._isForAngular) {
65
- //-- stylesheetBundler
66
- this._stylesheetBundler = new ComponentStylesheetBundler(
67
- {
68
- workspaceRoot: this._opt.pkgPath,
69
- optimization: !this._opt.isDevMode,
70
- inlineFonts: true,
71
- preserveSymlinks: false,
72
- sourcemap: this._opt.isDevMode ? "inline" : false,
73
- outputNames: { bundles: "[name]", media: "media/[name]" },
74
- includePaths: [],
75
- externalDependencies: [],
76
- target: transformSupportedBrowsersToTargets(browserslist(["Chrome > 78"])),
77
- postcssConfiguration: {
78
- plugins: [["css-has-pseudo"]],
79
- },
80
- tailwindConfiguration: undefined,
81
- cacheOptions: {
82
- enabled: true,
83
- path: ".cache/angular",
84
- basePath: ".cache",
85
- },
86
- },
87
- "scss",
88
- this._opt.isDevMode,
89
- );
90
- }
91
57
  }
92
58
 
93
- private _parseTsConfig(): ITsConfigInfo {
94
- const config = this._loadTsConfig();
95
- const compilerHost = this._createCompilerHost(config.options);
96
- return {
97
- ...config,
98
- compilerHost,
99
- };
100
- }
101
-
102
- private _loadTsConfig() {
59
+ private _parseTsConfig() {
103
60
  const tsconfigPath = path.resolve(this._opt.pkgPath, "tsconfig.json");
104
61
  const tsconfig = FsUtils.readJson(tsconfigPath);
105
62
  const parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._opt.pkgPath, {
@@ -119,7 +76,10 @@ export class SdTsCompiler {
119
76
  };
120
77
  }
121
78
 
122
- private _createCompilerHost(compilerOptions: ts.CompilerOptions) {
79
+ private _createCompilerHost(
80
+ compilerOptions: ts.CompilerOptions,
81
+ modifiedFileSet: Set<TNormPath>,
82
+ ) {
123
83
  const compilerHost = ts.createCompilerHost(compilerOptions);
124
84
 
125
85
  const baseGetSourceFile = compilerHost.getSourceFile;
@@ -155,12 +115,6 @@ export class SdTsCompiler {
155
115
  return sf;
156
116
  };
157
117
 
158
- const baseReadFile = compilerHost.readFile;
159
- compilerHost.readFile = (fileName) => {
160
- this._watchFileSet.add(PathUtils.norm(fileName));
161
- return baseReadFile.call(compilerHost, fileName);
162
- };
163
-
164
118
  if (this._isForAngular) {
165
119
  (compilerHost as AngularCompilerHost).readResource = (fileName: string) => {
166
120
  return compilerHost.readFile(fileName) ?? "";
@@ -190,13 +144,30 @@ export class SdTsCompiler {
190
144
  };
191
145
 
192
146
  (compilerHost as AngularCompilerHost).getModifiedResourceFiles = () => {
193
- return new Set(Array.from(this._modifiedFileSet).map((item) => PathUtils.posix(item)));
147
+ return new Set(Array.from(modifiedFileSet).map((item) => PathUtils.posix(item)));
194
148
  };
195
149
  }
196
150
 
197
151
  return compilerHost;
198
152
  }
199
153
 
154
+ private async _getOrCreateStyleBundleWorkerAsync() {
155
+ if (this._stylesheetBundlingWorker) {
156
+ return this._stylesheetBundlingWorker;
157
+ }
158
+
159
+ this._stylesheetBundlingWorker = new SdWorker<TStyleBundlerWorkerType>(
160
+ import.meta.resolve("../workers/style-bundler.worker"),
161
+ );
162
+
163
+ await this._stylesheetBundlingWorker.run(
164
+ "prepare",
165
+ [this._opt.pkgPath, this._opt.isDevMode],
166
+ );
167
+
168
+ return this._stylesheetBundlingWorker;
169
+ }
170
+
200
171
  private async _bundleStylesheetAsync(
201
172
  data: string,
202
173
  containingFile: TNormPath,
@@ -215,24 +186,12 @@ export class SdTsCompiler {
215
186
  }
216
187
 
217
188
  try {
218
- const result =
219
- resourceFile != null
220
- ? await this._stylesheetBundler!.bundleFile(resourceFile)
221
- : await this._stylesheetBundler!.bundleInline(data, containingFile, "scss");
222
-
223
- if (result.referencedFiles) {
224
- for (const referencedFile of result.referencedFiles) {
225
- const depCacheSet = this._revDepCacheMap.getOrCreate(
226
- PathUtils.norm(referencedFile),
227
- new Set<TNormPath>(),
228
- );
229
- depCacheSet.add(fileNPath);
230
- }
189
+ const worker = this._stylesheetBundlingWorker!;
190
+ const result = await worker.run("bundle", [data, containingFile, resourceFile]);
231
191
 
232
- this._watchFileSet.adds(
233
- ...Array.from(result.referencedFiles.values())
234
- .map((item) => PathUtils.norm(item)),
235
- );
192
+ for (const referencedFile of result.referencedFiles ?? []) {
193
+ // 참조하는 파일과 참조된 파일 사이의 의존성 관계 추가
194
+ this._depCache.addImport(fileNPath, PathUtils.norm(referencedFile), 0);
236
195
  }
237
196
 
238
197
  this._stylesheetBundlingResultMap.set(fileNPath, result);
@@ -255,111 +214,96 @@ export class SdTsCompiler {
255
214
  });
256
215
  }
257
216
 
258
- public async compileAsync(modifiedFileSet: Set<TNormPath>): Promise<ISdTsCompilerResult> {
217
+ async compileAsync(modifiedFileSet: Set<TNormPath>): Promise<ISdTsCompilerResult> {
259
218
  this._perf = new SdCliPerformanceTimer("esbuild compile");
260
219
 
261
- this._modifiedFileSet = new Set(modifiedFileSet);
262
- this._affectedFileSet = new Set<TNormPath>();
263
-
264
- /*for (const mod of modifiedFileSet) {
265
- const workerImporters = this.#workerRevDependencyCacheMap.get(mod);
266
- if (workerImporters) {
267
- this.#modifiedFileSet.adds(...workerImporters);
268
- } else {
269
- this.#modifiedFileSet.add(mod);
270
- }
271
- }*/
272
-
273
- const tsconf = this._parseTsConfig();
274
-
275
- const prepareResult = await this._prepareAsync(tsconf);
220
+ const prepareResult = await this._prepareAsync(modifiedFileSet);
276
221
 
277
- const [buildResult, lintResults] = await Promise.all([
278
- this._buildAsync(tsconf),
279
- this._lintAsync(),
222
+ const [globalStyleSheet, buildResult, lintResults] = await Promise.all([
223
+ this._buildGlobalStyleAsync(),
224
+ this._build(prepareResult),
225
+ this._lintAsync(prepareResult),
280
226
  ]);
281
227
 
282
228
  this._debug(`빌드 완료됨`, this._perf.toString());
283
- this._debug(`영향 받은 파일: ${this._affectedFileSet.size}개`);
284
- this._debug(`감시 중인 파일: ${this._watchFileSet.size}개`);
229
+ this._debug(`영향 받은 파일: ${prepareResult.affectedFileSet.size}개`);
230
+ this._debug(`감시 중인 파일: ${prepareResult.watchFileSet.size}개`);
285
231
 
286
232
  return {
287
233
  messages: [
288
- ...prepareResult.messages,
289
234
  ...SdCliConvertMessageUtils.convertToBuildMessagesFromTsDiag(buildResult.diagnostics),
290
235
  ...SdCliConvertMessageUtils.convertToBuildMessagesFromEslint(lintResults),
291
236
  ],
292
- watchFileSet: this._watchFileSet,
293
- affectedFileSet: this._affectedFileSet,
237
+ affectedFileSet: prepareResult.affectedFileSet,
238
+ watchFileSet: prepareResult.watchFileSet,
294
239
  stylesheetBundlingResultMap: this._stylesheetBundlingResultMap,
295
240
  emittedFilesCacheMap: this._emittedFilesCacheMap,
296
- emitFileSet: buildResult.emitFileSet,
241
+ emitFileSet: new Set([...buildResult.emitFileSet, globalStyleSheet].filterExists()),
297
242
  };
298
243
  }
299
244
 
300
- private async _prepareAsync(tsconf: ITsConfigInfo) {
301
- if (this._modifiedFileSet.size !== 0) {
302
- this._debug(`영향 받은 파일 추적 중... (구 의존성)`);
245
+ private async _prepareAsync(modifiedFileSet: Set<TNormPath>): Promise<IPrepareResult> {
246
+ const worker = await this._getOrCreateStyleBundleWorkerAsync();
303
247
 
304
- this._perf.run("영향 받은 파일 추적", () => {
305
- for (const modifiedFile of this._modifiedFileSet) {
306
- this._affectedFileSet.add(modifiedFile);
248
+ const tsconfig = this._parseTsConfig();
307
249
 
308
- this._affectedFileSet.adds(...(this._revDepCacheMap.get(modifiedFile) ?? []));
250
+ if (modifiedFileSet.size !== 0) {
251
+ this._debug(`캐시 무효화 및 초기화 중...`);
252
+
253
+ await this._perf.run("캐시 무효화 및 초기화", async () => {
254
+ // 기존 의존성에 의해 영향받는 파일들 계산
255
+ const affectedFileSet = this._depCache.getAffectedFileSet(modifiedFileSet);
309
256
 
310
- // .d.ts .js 대응
311
- if (modifiedFile.endsWith(".d.ts")) {
312
- const jsEquivalent = PathUtils.norm(modifiedFile.replace(/\.d\.ts$/, ".js"));
313
- this._affectedFileSet.add(jsEquivalent);
257
+ const getTreeText = (node: ISdAffectedFileTreeNode, indent = "") => {
258
+ let result = indent + node.fileNPath + "\n";
259
+ for (const child of node.children) {
260
+ result += getTreeText(child, indent + " ");
314
261
  }
315
- }
316
- });
317
262
 
318
- this._debug(`캐시 무효화 및 초기화 중...`);
263
+ return result;
264
+ };
265
+
266
+ const affectedFileTree = this._depCache.getAffectedFileTree(modifiedFileSet);
267
+ this._debug(`
268
+ 영향받은 기존파일:
269
+ ${affectedFileTree.map(item => getTreeText(item)).join("\n")}`.trim());
319
270
 
320
- this._perf.run("캐시 무효화 초기화", () => {
321
- this._stylesheetBundler?.invalidate(this._affectedFileSet);
271
+ // 스타일 번들러에서 영향받은 파일 관련 항목 무효화
272
+ await worker.run("invalidate", [affectedFileSet]);
322
273
 
323
- for (const affectedFile of this._affectedFileSet) {
274
+ // 의존성 캐시에서 영향받은 파일 관련 항목 무효화
275
+ this._depCache.invalidates(affectedFileSet);
276
+
277
+ // 내부 캐시에서 영향받은 파일 관련 항목 무효화
278
+ for (const affectedFile of affectedFileSet) {
324
279
  this._emittedFilesCacheMap.delete(affectedFile);
325
280
  this._sourceFileCacheMap.delete(affectedFile);
326
281
  this._stylesheetBundlingResultMap.delete(affectedFile);
327
- this._watchFileSet.delete(affectedFile);
328
-
329
- for (const [key, deps] of this._revDepCacheMap.entries()) {
330
- if (key === affectedFile) {
331
- this._revDepCacheMap.delete(key);
332
- continue;
333
- }
334
-
335
- if (deps.has(affectedFile)) {
336
- deps.delete(affectedFile);
337
- if (deps.size === 0) {
338
- this._revDepCacheMap.delete(key);
339
- }
340
- }
341
- }
342
282
  }
343
283
  });
344
284
  }
345
285
 
346
286
  this._debug(`ts.Program 생성 중...`);
347
287
 
288
+ const compilerHost = this._perf.run("ts.CompilerHost 생성", () => {
289
+ return this._createCompilerHost(tsconfig.options, modifiedFileSet);
290
+ });
291
+
348
292
  this._perf.run("ts.Program 생성", () => {
349
293
  if (this._isForAngular) {
350
294
  this._ngProgram = new NgtscProgram(
351
- tsconf.fileNames,
352
- tsconf.options,
353
- tsconf.compilerHost,
295
+ tsconfig.fileNames,
296
+ tsconfig.options,
297
+ compilerHost,
354
298
  this._ngProgram,
355
299
  );
356
300
  this._program = this._ngProgram.getTsProgram();
357
301
  }
358
302
  else {
359
303
  this._program = ts.createProgram(
360
- tsconf.fileNames,
361
- tsconf.options,
362
- tsconf.compilerHost,
304
+ tsconfig.fileNames,
305
+ tsconfig.options,
306
+ compilerHost,
363
307
  this._program,
364
308
  );
365
309
  }
@@ -373,86 +317,40 @@ export class SdTsCompiler {
373
317
 
374
318
  this._debug(`새 의존성 분석 중...`);
375
319
 
376
- const messages: ISdBuildMessage[] = [];
377
- const analysed1 = this._perf.run("새 의존성 분석", () => {
378
- const analysed = SdTsDependencyAnalyzer.analyze(
320
+ this._perf.run("새 의존성 분석", () => {
321
+ // SdTsDependencyAnalyzer를 통해 의존성 분석 SdDepCache 업데이트
322
+ SdDependencyAnalyzer.analyze(
379
323
  this._program!,
380
- tsconf.compilerHost,
324
+ compilerHost,
381
325
  this._opt.watchScopePaths,
326
+ this._depCache,
382
327
  );
383
- messages.push(...analysed.messages);
384
-
385
- for (const sf of analysed.sourceFileSet) {
386
- const filePath = PathUtils.norm(sf.fileName);
387
- const deps = analysed.allDepMap.get(filePath) ?? new Set<TNormPath>();
388
-
389
- for (const dep of deps) {
390
- const depCache = this._revDepCacheMap.getOrCreate(dep, new Set<TNormPath>());
391
- depCache.add(filePath);
392
- }
393
-
394
- if (this._ngProgram) {
395
- if (this._ngProgram.compiler.ignoreForEmit.has(sf)) {
396
- continue;
397
- }
398
-
399
- for (const dep of this._ngProgram.compiler.getResourceDependencies(sf)) {
400
- const ref = this._revDepCacheMap.getOrCreate(
401
- PathUtils.norm(dep),
402
- new Set<TNormPath>(),
403
- );
404
- ref.add(filePath);
405
- }
406
- }
407
- }
408
-
409
- return analysed;
410
- });
411
-
412
- if (this._modifiedFileSet.size === 0) {
413
- this._debug(`영향 받은 파일 추가 중... (새 의존성)`);
414
328
 
415
- this._perf.run("영향 받은 파일 추가 중 (새 의존성)", () => {
416
- for (const sf of analysed1.sourceFileSet) {
417
- if (!this._opt.watchScopePaths.some((scopePath) => PathUtils.isChildPath(
418
- sf.fileName,
419
- scopePath,
420
- ))) {
421
- continue;
422
- }
423
-
424
- this._affectedFileSet.add(PathUtils.norm(sf.fileName));
425
- }
426
- });
427
- }
428
-
429
- for (const dep of this._revDepCacheMap.keys()) {
430
- if (this._modifiedFileSet.has(dep)) {
431
- this._affectedFileSet.adds(
432
- ...Array.from(this._revDepCacheMap.get(dep)!).mapMany((item) =>
433
- [
434
- item,
435
- // .d.ts면 .js파일도 affected에 추가
436
- item.endsWith(".d.ts") ? PathUtils.norm(item.replace(/\.d\.ts$/, ".js")) : undefined,
437
- ].filterExists(),
438
- ),
329
+ // Angular 리소스 의존성 추가
330
+ if (this._ngProgram) {
331
+ SdDependencyAnalyzer.analyzeAngularResources(
332
+ this._ngProgram,
333
+ this._opt.watchScopePaths,
334
+ this._depCache,
439
335
  );
440
336
  }
337
+ });
441
338
 
442
- // dep이 emit된적이 없으면 affected에 추가해야함.
443
- // dep파일이 추가된후 기존 파일에서 import하면 dep파일이 affected에 포함이 안되는 현상 때문
444
- if (!this._emittedFilesCacheMap.has(dep)) {
445
- this._affectedFileSet.add(dep);
446
- }
447
- }
339
+ const affectedFileSet = modifiedFileSet.size === 0
340
+ ? this._depCache.getFiles()
341
+ : this._depCache.getAffectedFileSet(modifiedFileSet);
342
+ const watchFileSet = this._depCache.getFiles();
448
343
 
449
344
  return {
450
- messages,
345
+ tsconfig,
346
+ compilerHost,
347
+ affectedFileSet,
348
+ watchFileSet,
451
349
  };
452
350
  }
453
351
 
454
- private async _lintAsync() {
455
- const lintFilePaths = Array.from(this._affectedFileSet)
352
+ private async _lintAsync(prepareResult: IPrepareResult) {
353
+ const lintFilePaths = Array.from(prepareResult.affectedFileSet)
456
354
  .filter((item) => PathUtils.isChildPath(item, this._opt.pkgPath))
457
355
  .filter((item) => (
458
356
  (!item.endsWith(".d.ts") && item.endsWith(".ts")) ||
@@ -470,7 +368,6 @@ export class SdTsCompiler {
470
368
  overrideConfig: {
471
369
  languageOptions: {
472
370
  parserOptions: {
473
- // parser: tseslint.parser,
474
371
  project: null,
475
372
  programs: [this._program],
476
373
  },
@@ -478,16 +375,45 @@ export class SdTsCompiler {
478
375
  },
479
376
  });
480
377
  return await linter.lintFiles(lintFilePaths);
378
+ }
379
+
380
+ private async _buildGlobalStyleAsync() {
381
+ //-- global style
382
+ if (
383
+ this._opt.globalStyleFilePath != null &&
384
+ FsUtils.exists(this._opt.globalStyleFilePath) &&
385
+ !this._emittedFilesCacheMap.has(this._opt.globalStyleFilePath)
386
+ ) {
387
+ this._debug(`전역 스타일 번들링 중...`);
388
+
389
+ await this._perf.run("전역 스타일 번들링", async () => {
390
+ const data = await FsUtils.readFileAsync(this._opt.globalStyleFilePath!);
391
+ const stylesheetBundlingResult = await this._bundleStylesheetAsync(
392
+ data,
393
+ this._opt.globalStyleFilePath!,
394
+ this._opt.globalStyleFilePath,
395
+ );
396
+ const emitFileInfos = this._emittedFilesCacheMap.getOrCreate(
397
+ this._opt.globalStyleFilePath!,
398
+ [],
399
+ );
400
+ emitFileInfos.push({
401
+ outAbsPath: PathUtils.norm(
402
+ this._opt.pkgPath,
403
+ path.relative(path.resolve(this._opt.pkgPath, "src"), this._opt.globalStyleFilePath!)
404
+ .replace(/\.scss$/, ".css"),
405
+ ),
406
+ text: stylesheetBundlingResult.contents ?? "",
407
+ });
408
+ });
409
+
410
+ return this._opt.globalStyleFilePath;
411
+ }
481
412
 
482
- // return await this.#lintWorker.run("lint", [
483
- // {
484
- // cwd: this.#pkgPath,
485
- // fileSet: this.#affectedFileSet,
486
- // },
487
- // ]);
413
+ return undefined;
488
414
  }
489
415
 
490
- private async _buildAsync(tsconf: ITsConfigInfo) {
416
+ private _build(prepareResult: IPrepareResult) {
491
417
  const emitFileSet = new Set<TNormPath>();
492
418
  const diagnostics: ts.Diagnostic[] = [];
493
419
 
@@ -507,7 +433,7 @@ export class SdTsCompiler {
507
433
 
508
434
  this._debug(`개별 파일 진단 수집 중...`);
509
435
 
510
- for (const affectedFile of this._affectedFileSet) {
436
+ for (const affectedFile of prepareResult.affectedFileSet) {
511
437
  if (!PathUtils.isChildPath(affectedFile, this._opt.pkgPath)) continue;
512
438
 
513
439
  const affectedSourceFile = this._program!.getSourceFile(affectedFile);
@@ -566,7 +492,7 @@ export class SdTsCompiler {
566
492
  // affected에 새로 추가된 파일은 포함되지 않는 현상이 있어 sourceFileSet으로 바꿈
567
493
  // 비교해보니, 딱히 getSourceFiles라서 더 느려지는것 같지는 않음
568
494
  // 그래도 affected로 다시 테스트 (조금이라도 더 빠르게)
569
- for (const affectedFile of this._affectedFileSet) {
495
+ for (const affectedFile of prepareResult.affectedFileSet) {
570
496
  if (this._emittedFilesCacheMap.has(affectedFile)) continue;
571
497
 
572
498
  const sf = this._program!.getSourceFile(affectedFile);
@@ -584,7 +510,7 @@ export class SdTsCompiler {
584
510
  sf,
585
511
  (fileName, text, writeByteOrderMark, onError, sourceFiles, data) => {
586
512
  if (!sourceFiles || sourceFiles.length === 0) {
587
- tsconf.compilerHost.writeFile(
513
+ prepareResult.compilerHost.writeFile(
588
514
  fileName,
589
515
  text,
590
516
  writeByteOrderMark,
@@ -607,7 +533,11 @@ export class SdTsCompiler {
607
533
  );
608
534
 
609
535
  if (PathUtils.isChildPath(sourceFile.fileName, this._opt.pkgPath)) {
610
- const real = this._convertOutputToReal(fileName, tsconf.distPath, text);
536
+ const real = this._convertOutputToReal(
537
+ fileName,
538
+ prepareResult.tsconfig.distPath,
539
+ text,
540
+ );
611
541
 
612
542
  emitFileInfoCaches.push({
613
543
  outAbsPath: real.filePath,
@@ -627,37 +557,6 @@ export class SdTsCompiler {
627
557
  }
628
558
  });
629
559
 
630
- //-- global style
631
- if (
632
- this._opt.globalStyleFilePath != null &&
633
- FsUtils.exists(this._opt.globalStyleFilePath) &&
634
- !this._emittedFilesCacheMap.has(this._opt.globalStyleFilePath)
635
- ) {
636
- this._debug(`전역 스타일 번들링 중...`);
637
-
638
- await this._perf.run("전역 스타일 번들링", async () => {
639
- const data = FsUtils.readFile(this._opt.globalStyleFilePath!);
640
- const stylesheetBundlingResult = await this._bundleStylesheetAsync(
641
- data,
642
- this._opt.globalStyleFilePath!,
643
- this._opt.globalStyleFilePath,
644
- );
645
- const emitFileInfos = this._emittedFilesCacheMap.getOrCreate(
646
- this._opt.globalStyleFilePath!,
647
- [],
648
- );
649
- emitFileInfos.push({
650
- outAbsPath: PathUtils.norm(
651
- this._opt.pkgPath,
652
- path.relative(path.resolve(this._opt.pkgPath, "src"), this._opt.globalStyleFilePath!)
653
- .replace(/\.scss$/, ".css"),
654
- ),
655
- text: stylesheetBundlingResult.contents ?? "",
656
- });
657
- emitFileSet.add(this._opt.globalStyleFilePath!);
658
- });
659
- }
660
-
661
560
  return {
662
561
  emitFileSet,
663
562
  diagnostics,
@@ -693,6 +592,12 @@ export class SdTsCompiler {
693
592
  interface ITsConfigInfo {
694
593
  fileNames: string[];
695
594
  options: ts.CompilerOptions;
696
- compilerHost: ts.CompilerHost;
697
595
  distPath: string;
596
+ }
597
+
598
+ interface IPrepareResult {
599
+ tsconfig: ITsConfigInfo;
600
+ compilerHost: ts.CompilerHost;
601
+ affectedFileSet: Set<TNormPath>;
602
+ watchFileSet: Set<TNormPath>;
698
603
  }
@@ -1,6 +1,10 @@
1
1
  import { ISdBuildRunnerWorkerRequest } from "./build-runner.types";
2
2
  import { ISdBuildMessage, ISdBuildRunnerResult } from "./build.types";
3
3
  import { ESLint } from "eslint";
4
+ import { TNormPath } from "@simplysm/sd-core-node";
5
+ import {
6
+ ComponentStylesheetResult,
7
+ } from "@angular/build/src/tools/esbuild/angular/component-stylesheets";
4
8
 
5
9
  export interface TServerWorkerType {
6
10
  methods: {
@@ -35,3 +39,16 @@ export interface TSdBuildRunnerWorkerType {
35
39
  complete: ISdBuildRunnerResult;
36
40
  };
37
41
  }
42
+
43
+
44
+ export interface TStyleBundlerWorkerType {
45
+ methods: {
46
+ prepare: { params: [string, boolean]; returnType: void },
47
+ bundle: {
48
+ params: [string, TNormPath, TNormPath | null],
49
+ returnType: ComponentStylesheetResult
50
+ },
51
+ invalidate: { params: [Set<TNormPath>], returnType: void }
52
+ };
53
+ events: {};
54
+ }