@simplysm/sd-cli 11.1.17 → 11.1.21

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 (56) hide show
  1. package/dist/build-tools/SdLinter.d.ts +1 -1
  2. package/dist/build-tools/SdLinter.js +2 -2
  3. package/dist/build-tools/SdLinter.js.map +1 -1
  4. package/dist/build-tools/SdNgBundler.d.ts +4 -2
  5. package/dist/build-tools/SdNgBundler.js +3 -2
  6. package/dist/build-tools/SdNgBundler.js.map +1 -1
  7. package/dist/build-tools/{SdTsBundler.d.ts → SdServerBundler.d.ts} +6 -2
  8. package/dist/build-tools/{SdTsBundler.js → SdServerBundler.js} +18 -14
  9. package/dist/build-tools/SdServerBundler.js.map +1 -0
  10. package/dist/build-tools/SdTsCompiler.d.ts +2 -2
  11. package/dist/build-tools/SdTsCompiler.js +10 -12
  12. package/dist/build-tools/SdTsCompiler.js.map +1 -1
  13. package/dist/builders/SdCliClientBuilder.d.ts +0 -1
  14. package/dist/builders/SdCliClientBuilder.js +32 -21
  15. package/dist/builders/SdCliClientBuilder.js.map +1 -1
  16. package/dist/builders/SdCliServerBuilder.js +31 -31
  17. package/dist/builders/SdCliServerBuilder.js.map +1 -1
  18. package/dist/builders/SdCliTsLibBuilder.js +22 -12
  19. package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
  20. package/dist/bundle-plugins/sdNgPlugin.d.ts +2 -0
  21. package/dist/bundle-plugins/sdNgPlugin.js +2 -1
  22. package/dist/bundle-plugins/sdNgPlugin.js.map +1 -1
  23. package/dist/bundle-plugins/sdServerPlugin.d.ts +15 -0
  24. package/dist/bundle-plugins/sdServerPlugin.js +132 -0
  25. package/dist/bundle-plugins/sdServerPlugin.js.map +1 -0
  26. package/dist/commons.d.ts +0 -1
  27. package/dist/entry/SdCliLocalUpdate.js +2 -2
  28. package/dist/entry/SdCliLocalUpdate.js.map +1 -1
  29. package/dist/entry/SdCliProject.js +1 -1
  30. package/dist/entry/SdCliProject.js.map +1 -1
  31. package/dist/index.d.ts +2 -3
  32. package/dist/index.js +2 -3
  33. package/dist/index.js.map +1 -1
  34. package/package.json +5 -5
  35. package/src/build-tools/SdLinter.ts +2 -2
  36. package/src/build-tools/SdNgBundler.ts +7 -4
  37. package/src/build-tools/{SdTsBundler.ts → SdServerBundler.ts} +22 -18
  38. package/src/build-tools/SdTsCompiler.ts +12 -14
  39. package/src/builders/SdCliClientBuilder.ts +36 -30
  40. package/src/builders/SdCliServerBuilder.ts +38 -39
  41. package/src/builders/SdCliTsLibBuilder.ts +24 -14
  42. package/src/bundle-plugins/sdNgPlugin.ts +3 -1
  43. package/src/bundle-plugins/sdServerPlugin.ts +211 -0
  44. package/src/commons.ts +0 -1
  45. package/src/entry/SdCliLocalUpdate.ts +3 -8
  46. package/src/entry/SdCliProject.ts +1 -1
  47. package/src/index.ts +2 -3
  48. package/dist/build-tools/SdTsBundler.js.map +0 -1
  49. package/dist/bundle-plugins/sdLoadedFilesPlugin.d.ts +0 -4
  50. package/dist/bundle-plugins/sdLoadedFilesPlugin.js +0 -15
  51. package/dist/bundle-plugins/sdLoadedFilesPlugin.js.map +0 -1
  52. package/dist/bundle-plugins/sdTscPlugin.d.ts +0 -5
  53. package/dist/bundle-plugins/sdTscPlugin.js +0 -21
  54. package/dist/bundle-plugins/sdTscPlugin.js.map +0 -1
  55. package/src/bundle-plugins/sdLoadedFilesPlugin.ts +0 -19
  56. package/src/bundle-plugins/sdTscPlugin.ts +0 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/sd-cli",
3
- "version": "11.1.17",
3
+ "version": "11.1.21",
4
4
  "description": "심플리즘 패키지 - CLI",
5
5
  "author": "김석래",
6
6
  "repository": {
@@ -23,10 +23,10 @@
23
23
  "@angular/compiler-cli": "^17.0.7",
24
24
  "@angular/core": "^17.0.7",
25
25
  "@electron/rebuild": "^3.4.1",
26
- "@simplysm/sd-core-common": "11.1.17",
27
- "@simplysm/sd-core-node": "11.1.17",
28
- "@simplysm/sd-service-server": "11.1.17",
29
- "@simplysm/sd-storage": "11.1.17",
26
+ "@simplysm/sd-core-common": "11.1.21",
27
+ "@simplysm/sd-core-node": "11.1.21",
28
+ "@simplysm/sd-service-server": "11.1.21",
29
+ "@simplysm/sd-storage": "11.1.21",
30
30
  "browserslist": "^4.22.2",
31
31
  "cordova": "^12.0.0",
32
32
  "electron": "^27.1.3",
@@ -3,8 +3,8 @@ import {ESLint} from "eslint";
3
3
  import ts from "typescript";
4
4
 
5
5
  export abstract class SdLinter {
6
- static async lintAsync(filePaths: string[], tsProgram: ts.Program | undefined): Promise<ISdCliPackageBuildResult[]> {
7
- const sourceFilePaths = filePaths.filter((item) =>
6
+ static async lintAsync(fileSet: Iterable<string>, tsProgram: ts.Program | undefined): Promise<ISdCliPackageBuildResult[]> {
7
+ const sourceFilePaths = Array.from(fileSet).filter((item) =>
8
8
  (!item.endsWith(".d.ts") && item.endsWith(".ts")) ||
9
9
  item.endsWith(".js") ||
10
10
  item.endsWith(".cjs") ||
@@ -40,6 +40,7 @@ import {InlineCriticalCssProcessor} from "@angular-devkit/build-angular/src/util
40
40
  import {SdNgBundlerContext} from "./SdNgBundlerContext";
41
41
  import {INgResultCache, sdNgPlugin} from "../bundle-plugins/sdNgPlugin";
42
42
  import {MemoryLoadResultCache} from "@angular-devkit/build-angular/src/tools/esbuild/load-result-cache";
43
+ import ts from "typescript";
43
44
 
44
45
  export class SdNgBundler {
45
46
  // private readonly _sourceFileCache = new SourceFileCache(
@@ -91,8 +92,9 @@ export class SdNgBundler {
91
92
  }
92
93
 
93
94
  public async bundleAsync(): Promise<{
94
- filePaths: string[],
95
- affectedFilePaths: string[],
95
+ program: ts.Program;
96
+ watchFileSet: Set<string>,
97
+ affectedFileSet: Set<string>,
96
98
  results: ISdCliPackageBuildResult[]
97
99
  }> {
98
100
  const logger = Logger.get(["simplysm", "sd-cli", "SdNgBundler", "bundleAsync"]);
@@ -208,8 +210,9 @@ export class SdNgBundler {
208
210
  logger.debug(`[${path.basename(this._opt.pkgPath)}] 번들링중 영향받은 파일`, Array.from(this.#ngResultCache.affectedFileSet!));
209
211
 
210
212
  return {
211
- filePaths: Array.from(this.#ngResultCache.watchFileSet!),
212
- affectedFilePaths: Array.from(this.#ngResultCache.affectedFileSet!),
213
+ program: this.#ngResultCache.program!,
214
+ watchFileSet: this.#ngResultCache.watchFileSet!,
215
+ affectedFileSet: this.#ngResultCache.affectedFileSet!,
213
216
  results
214
217
  };
215
218
  }
@@ -1,14 +1,15 @@
1
1
  import {ISdCliPackageBuildResult} from "../commons";
2
2
  import esbuild from "esbuild";
3
3
  import path from "path";
4
+ import {IServerBundlerResultCache, sdServerPlugin} from "../bundle-plugins/sdServerPlugin";
4
5
  import ts from "typescript";
5
- import {FsUtil} from "@simplysm/sd-core-node";
6
- import {sdLoadedFilesPlugin} from "../bundle-plugins/sdLoadedFilesPlugin";
7
- import {sdTscPlugin} from "../bundle-plugins/sdTscPlugin";
8
6
 
9
- export class SdTsBundler {
7
+ export class SdServerBundler {
10
8
  #context?: esbuild.BuildContext;
11
9
 
10
+ #modifiedFileSet = new Set<string>();
11
+ #resultCache: Partial<IServerBundlerResultCache> = {};
12
+
12
13
  constructor(private readonly _opt: {
13
14
  dev: boolean;
14
15
  pkgPath: string;
@@ -17,12 +18,18 @@ export class SdTsBundler {
17
18
  }) {
18
19
  }
19
20
 
21
+ public markForChanges(filePaths: string[]): void {
22
+ for (const filePath of filePaths) {
23
+ this.#modifiedFileSet.add(path.normalize(filePath));
24
+ }
25
+ }
26
+
20
27
  async bundleAsync(): Promise<{
21
- filePaths: string[];
28
+ program: ts.Program;
29
+ watchFileSet: Set<string>;
30
+ affectedFileSet: Set<string>;
22
31
  results: ISdCliPackageBuildResult[];
23
32
  }> {
24
- const loadFilePathSet = new Set<string>();
25
-
26
33
  if (!this.#context) {
27
34
  this.#context = await esbuild.context({
28
35
  entryPoints: this._opt.entryPoints,
@@ -65,7 +72,6 @@ export class SdTsBundler {
65
72
  },
66
73
  platform: "node",
67
74
  logLevel: "silent",
68
- // packages: "external",
69
75
  external: this._opt.external,
70
76
  banner: {
71
77
  js: `
@@ -78,16 +84,12 @@ const __filename = __fileURLToPath__(import.meta.url);
78
84
  const __dirname = __path__.dirname(__filename);`.trim()
79
85
  },
80
86
  plugins: [
81
- sdTscPlugin({
82
- parsedTsconfig: ts.parseJsonConfigFileContent(
83
- FsUtil.readJson(path.resolve(this._opt.pkgPath, "tsconfig.json")),
84
- ts.sys,
85
- this._opt.pkgPath
86
- )
87
+ sdServerPlugin({
88
+ modifiedFileSet: this.#modifiedFileSet,
89
+ dev: this._opt.dev,
90
+ pkgPath: this._opt.pkgPath,
91
+ result: this.#resultCache
87
92
  }),
88
- sdLoadedFilesPlugin({
89
- loadedFileSet: loadFilePathSet
90
- })
91
93
  ]
92
94
  });
93
95
  }
@@ -101,7 +103,9 @@ const __dirname = __path__.dirname(__filename);`.trim()
101
103
  }
102
104
 
103
105
  return {
104
- filePaths: Array.from(loadFilePathSet).map(item => path.resolve(item)),
106
+ program: this.#resultCache.program!,
107
+ watchFileSet: this.#resultCache.watchFileSet!,
108
+ affectedFileSet: this.#resultCache.affectedFileSet!,
105
109
  results: [
106
110
  ...result.warnings.map((warn) => ({
107
111
  type: "build" as const,
@@ -99,8 +99,8 @@ export class SdTsCompiler {
99
99
  }
100
100
 
101
101
  public async buildAsync(): Promise<{
102
- filePaths: string[];
103
- affectedFilePaths: string[];
102
+ watchFileSet: Set<string>;
103
+ affectedFileSet: Set<string>;
104
104
  results: ISdCliPackageBuildResult[];
105
105
  }> {
106
106
  const markedChanges = this._markedChanges;
@@ -156,7 +156,7 @@ export class SdTsCompiler {
156
156
  }
157
157
 
158
158
  const diagnostics: ts.Diagnostic[] = [];
159
- const affectedFilePaths: string[] = [];
159
+ const affectedFileSet = new Set<string>();
160
160
 
161
161
  if (this._ngProgram) {
162
162
  diagnostics.push(...this._ngProgram.compiler.getOptionDiagnostics());
@@ -201,7 +201,7 @@ export class SdTsCompiler {
201
201
  diagnostics.push(...semanticResult.result);
202
202
 
203
203
  if ("fileName" in affectedSourceFile) {
204
- affectedFilePaths.push(path.resolve(affectedSourceFile.fileName));
204
+ affectedFileSet.add(path.normalize(affectedSourceFile.fileName));
205
205
  }
206
206
  }
207
207
 
@@ -209,21 +209,19 @@ export class SdTsCompiler {
209
209
  for (const markedChange of markedChanges) {
210
210
  const depsSet = this._styleDepsCache.get(markedChange);
211
211
  if (depsSet) {
212
- affectedFilePaths.push(...depsSet);
212
+ affectedFileSet.adds(...depsSet);
213
213
  }
214
214
  }
215
- affectedFilePaths.distinctThis();
216
215
  }
217
216
 
218
217
  const globalStyleFilePath = path.resolve(this._opt.pkgPath, "src/styles.scss");
219
218
  if (this._opt.globalStyle && FsUtil.exists(globalStyleFilePath) && markedChanges.includes(globalStyleFilePath)) {
220
- affectedFilePaths.push(globalStyleFilePath);
221
- affectedFilePaths.distinctThis();
219
+ affectedFileSet.add(globalStyleFilePath);
222
220
  }
223
221
 
224
222
  this._logger.debug(`[${path.basename(this._opt.pkgPath)}] 영향받는 파일 ${this._opt.emit ? "EMIT" : "CHECK"}...`);
225
223
 
226
- for (const affectedFilePath of affectedFilePaths) {
224
+ for (const affectedFilePath of affectedFileSet) {
227
225
  if (this._opt.globalStyle && affectedFilePath === globalStyleFilePath) {
228
226
  try {
229
227
  const content = await FsUtil.readFileAsync(affectedFilePath);
@@ -294,16 +292,16 @@ export class SdTsCompiler {
294
292
  }
295
293
  }
296
294
 
297
- this._logger.debug(`[${path.basename(this._opt.pkgPath)}] 영향받는 파일 ${this._opt.emit ? "EMIT" : "CHECK"} 완료`, affectedFilePaths);
295
+ this._logger.debug(`[${path.basename(this._opt.pkgPath)}] 영향받는 파일 ${this._opt.emit ? "EMIT" : "CHECK"} 완료`, affectedFileSet);
298
296
 
299
297
  const buildResults = diagnostics.map((item) => SdCliBuildResultUtil.convertFromTsDiag(item, this._opt.emit ? "build" : "check"));
300
298
 
301
299
  return {
302
- filePaths: [
300
+ watchFileSet: new Set([
303
301
  ...Array.from(this._styleDepsCache.keys()),
304
- ...this._builder.getSourceFiles().map(item => path.resolve(item.fileName))
305
- ],
306
- affectedFilePaths: affectedFilePaths,
302
+ ...this._builder.getSourceFiles().map(item => path.normalize(item.fileName))
303
+ ]),
304
+ affectedFileSet: affectedFileSet,
307
305
  results: buildResults
308
306
  };
309
307
  }
@@ -1,19 +1,14 @@
1
1
  import {EventEmitter} from "events";
2
2
  import {FsUtil, Logger, PathUtil, SdFsWatcher} from "@simplysm/sd-core-node";
3
- import {
4
- ISdCliBuilderResult,
5
- ISdCliClientPackageConfig,
6
- ISdCliConfig,
7
- ISdCliPackageBuildResult,
8
- ITsConfig
9
- } from "../commons";
3
+ import {ISdCliBuilderResult, ISdCliClientPackageConfig, ISdCliConfig, ISdCliPackageBuildResult} from "../commons";
10
4
  import {FunctionQueue} from "@simplysm/sd-core-common";
11
5
  import path from "path";
12
6
  import {SdNgBundler} from "../build-tools/SdNgBundler";
13
7
  import {SdCliCordova} from "../build-tools/SdCliCordova";
14
8
  import {SdCliNgRoutesFileGenerator} from "../build-tools/SdCliNgRoutesFileGenerator";
15
9
  import {SdLinter} from "../build-tools/SdLinter";
16
- import ts from "typescript";
10
+
11
+ // import ts from "typescript";
17
12
 
18
13
  export class SdCliClientBuilder extends EventEmitter {
19
14
  private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliClientBuilder"]);
@@ -21,7 +16,7 @@ export class SdCliClientBuilder extends EventEmitter {
21
16
  private _builders?: SdNgBundler[];
22
17
  private _cordova?: SdCliCordova;
23
18
 
24
- #program?: ts.Program;
19
+ // #program?: ts.Program;
25
20
 
26
21
  public constructor(private readonly _projConf: ISdCliConfig,
27
22
  private readonly _pkgPath: string) {
@@ -47,7 +42,11 @@ export class SdCliClientBuilder extends EventEmitter {
47
42
  const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
48
43
  await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
49
44
 
50
- return await this._runAsync({dev: false});
45
+ const result = await this._runAsync({dev: false});
46
+ return {
47
+ affectedFilePaths: Array.from(result.affectedFileSet),
48
+ buildResults: result.buildResults
49
+ };
51
50
  }
52
51
 
53
52
  public async watchAsync() {
@@ -64,13 +63,16 @@ export class SdCliClientBuilder extends EventEmitter {
64
63
  await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
65
64
 
66
65
  const result = await this._runAsync({dev: true});
67
- this.emit("complete", result);
66
+ this.emit("complete", {
67
+ affectedFilePaths: Array.from(result.affectedFileSet),
68
+ buildResults: result.buildResults
69
+ });
68
70
 
69
71
  this._debug("WATCH...");
70
72
  let changeFiles: string[] = [];
71
73
  const fnQ = new FunctionQueue();
72
74
  const watcher = SdFsWatcher
73
- .watch(result.watchFilePaths)
75
+ .watch(Array.from(result.watchFileSet))
74
76
  .onChange({delay: 100}, (changeInfos) => {
75
77
  changeFiles.push(...changeInfos.map((item) => item.path));
76
78
 
@@ -86,9 +88,12 @@ export class SdCliClientBuilder extends EventEmitter {
86
88
  }
87
89
 
88
90
  const watchResult = await this._runAsync({dev: true});
89
- this.emit("complete", watchResult);
91
+ this.emit("complete", {
92
+ affectedFilePaths: Array.from(watchResult.affectedFileSet),
93
+ buildResults: watchResult.buildResults
94
+ });
90
95
 
91
- watcher.add(watchResult.watchFilePaths);
96
+ watcher.add(watchResult.watchFileSet);
92
97
  });
93
98
  });
94
99
  }
@@ -96,8 +101,8 @@ export class SdCliClientBuilder extends EventEmitter {
96
101
  private async _runAsync(opt: {
97
102
  dev: boolean;
98
103
  }): Promise<{
99
- watchFilePaths: string[];
100
- affectedFilePaths: string[];
104
+ watchFileSet: Set<string>;
105
+ affectedFileSet: Set<string>;
101
106
  buildResults: ISdCliPackageBuildResult[];
102
107
  }> {
103
108
  const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as ("web" | "electron" | "cordova")[]);
@@ -131,20 +136,21 @@ export class SdCliClientBuilder extends EventEmitter {
131
136
 
132
137
  this._debug(`BUILD & CHECK...`);
133
138
  const buildResults = await Promise.all(this._builders.map((builder) => builder.bundleAsync()));
134
- const filePaths = buildResults.mapMany(item => item.filePaths).distinct();
135
- const affectedFilePaths = buildResults.mapMany(item => item.affectedFilePaths).distinct();
139
+ const watchFileSet = new Set(buildResults.mapMany(item => Array.from(item.watchFileSet)));
140
+ const affectedFileSet = new Set(buildResults.mapMany(item => Array.from(item.affectedFileSet)));
136
141
  const results = buildResults.mapMany((item) => item.results).distinct();
142
+ const firstProgram = buildResults.first()?.program;
137
143
 
138
144
  this._debug(`LINT...`);
139
- const tsConfig = FsUtil.readJson(path.resolve(this._pkgPath, "tsconfig.json")) as ITsConfig;
140
- const parsedTsConfig = ts.parseJsonConfigFileContent(tsConfig, ts.sys, this._pkgPath);
141
- this.#program = ts.createProgram({
142
- rootNames: parsedTsConfig.fileNames,
143
- options: parsedTsConfig.options,
144
- oldProgram: this.#program
145
- });
145
+ // const tsConfig = FsUtil.readJson(path.resolve(this._pkgPath, "tsconfig.json")) as ITsConfig;
146
+ // const parsedTsConfig = ts.parseJsonConfigFileContent(tsConfig, ts.sys, this._pkgPath);
147
+ // this.#program = ts.createProgram({
148
+ // rootNames: parsedTsConfig.fileNames,
149
+ // options: parsedTsConfig.options,
150
+ // oldProgram: this.#program
151
+ // });
146
152
  // const pkgFilePaths = filePaths.filter(item => PathUtil.isChildPath(item, this._pkgPath));
147
- const lintResults = await SdLinter.lintAsync(affectedFilePaths.filter(item => PathUtil.isChildPath(item, this._pkgPath)), this.#program);
153
+ const lintResults = await SdLinter.lintAsync(Array.from(affectedFileSet).filter(item => PathUtil.isChildPath(item, this._pkgPath)), firstProgram);
148
154
 
149
155
  if (!opt.dev && this._cordova) {
150
156
  this._debug("CORDOVA BUILD...");
@@ -154,13 +160,13 @@ export class SdCliClientBuilder extends EventEmitter {
154
160
  this._debug(`빌드 완료`);
155
161
  const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
156
162
  .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
157
- const watchFilePaths = filePaths.filter(item =>
163
+ const currWatchFileSet = new Set(Array.from(watchFileSet).filter(item =>
158
164
  PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
159
165
  localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
160
- );
166
+ ));
161
167
  return {
162
- watchFilePaths: watchFilePaths,
163
- affectedFilePaths: affectedFilePaths,
168
+ watchFileSet: currWatchFileSet,
169
+ affectedFileSet,
164
170
  buildResults: [...results, ...lintResults]
165
171
  };
166
172
  }
@@ -9,16 +9,14 @@ import {
9
9
  ITsConfig
10
10
  } from "../commons";
11
11
  import path from "path";
12
- import {SdTsCompiler} from "../build-tools/SdTsCompiler";
13
12
  import {SdLinter} from "../build-tools/SdLinter";
14
13
  import {FunctionQueue, ObjectUtil, StringUtil} from "@simplysm/sd-core-common";
15
- import {SdTsBundler} from "../build-tools/SdTsBundler";
14
+ import {SdServerBundler} from "../build-tools/SdServerBundler";
16
15
 
17
16
  export class SdCliServerBuilder extends EventEmitter {
18
17
  #logger = Logger.get(["simplysm", "sd-cli", "SdCliServerBuilder"]);
19
18
  #pkgConf: ISdCliServerPackageConfig;
20
- #builder?: SdTsBundler;
21
- #checker?: SdTsCompiler;
19
+ #builder?: SdServerBundler;
22
20
  #extModules?: { name: string; exists: boolean }[];
23
21
 
24
22
  public constructor(private readonly _projConf: ISdCliConfig,
@@ -45,20 +43,34 @@ export class SdCliServerBuilder extends EventEmitter {
45
43
  await FsUtil.writeFileAsync(confDistPath, JSON.stringify(this.#pkgConf.configs ?? {}, undefined, 2));
46
44
 
47
45
  const result = await this._runAsync({dev: true});
48
- this.emit("complete", result);
46
+ this.emit("complete", {
47
+ affectedFilePaths: Array.from(result.affectedFileSet),
48
+ buildResults: result.buildResults
49
+ });
49
50
 
50
51
  this._debug("WATCH...");
52
+ let changeFiles: string[] = [];
51
53
  const fnQ = new FunctionQueue();
52
54
  const watcher = SdFsWatcher
53
- .watch(result.watchFilePaths)
54
- .onChange({delay: 100}, () => {
55
+ .watch(Array.from(result.watchFileSet))
56
+ .onChange({delay: 100}, (changeInfos) => {
57
+ changeFiles.push(...changeInfos.map((item) => item.path));
58
+
55
59
  fnQ.runLast(async () => {
60
+ const currChangeFiles = [...changeFiles];
61
+ changeFiles = [];
62
+
56
63
  this.emit("change");
57
64
 
65
+ this.#builder!.markForChanges(currChangeFiles);
66
+
58
67
  const watchResult = await this._runAsync({dev: true});
59
- this.emit("complete", watchResult);
68
+ this.emit("complete", {
69
+ affectedFilePaths: Array.from(watchResult.affectedFileSet),
70
+ buildResults: watchResult.buildResults
71
+ });
60
72
 
61
- watcher.add(watchResult.watchFilePaths);
73
+ watcher.add(watchResult.watchFileSet);
62
74
  });
63
75
  });
64
76
  }
@@ -190,22 +202,22 @@ Options = UnsafeLegacyRenegotiation`.trim()
190
202
  `.trim());
191
203
  }
192
204
 
193
- return await this._runAsync({dev: false});
205
+ const result = await this._runAsync({dev: false});
206
+ return {
207
+ affectedFilePaths: Array.from(result.affectedFileSet),
208
+ buildResults: result.buildResults
209
+ };
194
210
  }
195
211
 
196
212
  private async _runAsync(opt: { dev: boolean }): Promise<{
197
- watchFilePaths: string[];
198
- affectedFilePaths: string[];
213
+ watchFileSet: Set<string>;
214
+ affectedFileSet: Set<string>;
199
215
  buildResults: ISdCliPackageBuildResult[];
200
216
  }> {
201
217
  this._debug(`BUILD 준비...`);
202
-
203
- this.#extModules = this.#extModules ?? await this._getExternalModulesAsync();
204
-
205
-
206
- this._debug(`BUILD...`);
207
218
  const tsConfig = FsUtil.readJson(path.resolve(this._pkgPath, "tsconfig.json")) as ITsConfig;
208
- this.#builder = this.#builder ?? new SdTsBundler({
219
+ this.#extModules = this.#extModules ?? await this._getExternalModulesAsync();
220
+ this.#builder = this.#builder ?? new SdServerBundler({
209
221
  dev: opt.dev,
210
222
  pkgPath: this._pkgPath,
211
223
  entryPoints: tsConfig.files ? tsConfig.files.map((item) => path.resolve(this._pkgPath, item)) : [
@@ -213,40 +225,27 @@ Options = UnsafeLegacyRenegotiation`.trim()
213
225
  ],
214
226
  external: this.#extModules.map((item) => item.name)
215
227
  });
216
- const buildResult = await this.#builder.bundleAsync();
217
228
 
218
- this._debug("CHECK...");
219
- this.#checker = this.#checker ?? new SdTsCompiler({
220
- pkgPath: this._pkgPath,
221
- emit: false,
222
- emitDts: false,
223
- globalStyle: false
224
- });
225
- const checkResult = await this.#checker.buildAsync();
229
+ this._debug(`BUILD & CHECK...`);
230
+ const buildResult = await this.#builder.bundleAsync();
226
231
 
227
232
  //-- filePaths
228
233
 
229
- const filePaths = [
230
- ...buildResult.filePaths,
231
- ...checkResult.filePaths
232
- ];
233
- const pkgFilePaths = filePaths.filter(item => PathUtil.isChildPath(item, this._pkgPath));
234
-
235
234
  const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
236
235
  .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
237
- const watchFilePaths = filePaths.filter(item =>
236
+ const watchFileSet = new Set(Array.from(buildResult.watchFileSet).filter(item =>
238
237
  PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
239
238
  localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
240
- );
239
+ ));
241
240
 
242
241
  this._debug(`LINT...`);
243
- const lintResults = await SdLinter.lintAsync(pkgFilePaths, this.#checker!.program);
242
+ const lintResults = await SdLinter.lintAsync(Array.from(buildResult.affectedFileSet).filter(item => PathUtil.isChildPath(item, this._pkgPath)), buildResult.program);
244
243
 
245
244
  this._debug(`빌드 완료`);
246
245
  return {
247
- watchFilePaths,
248
- affectedFilePaths: pkgFilePaths, //checkResult.affectedFilePaths,
249
- buildResults: [...buildResult.results, ...checkResult.results, ...lintResults]
246
+ watchFileSet,
247
+ affectedFileSet: buildResult.affectedFileSet,
248
+ buildResults: [...buildResult.results, ...lintResults]
250
249
  };
251
250
  }
252
251
 
@@ -35,7 +35,11 @@ export class SdCliTsLibBuilder extends EventEmitter {
35
35
  await SdCliIndexFileGenerator.runAsync(this._pkgPath, this._pkgConf.polyfills);
36
36
  }
37
37
 
38
- return await this._runAsync();
38
+ const result = await this._runAsync();
39
+ return {
40
+ affectedFilePaths: Array.from(result.affectedFileSet),
41
+ buildResults: result.buildResults
42
+ };
39
43
  }
40
44
 
41
45
  public async watchAsync(): Promise<void> {
@@ -50,12 +54,15 @@ export class SdCliTsLibBuilder extends EventEmitter {
50
54
  }
51
55
 
52
56
  const result = await this._runAsync();
53
- this.emit("complete", result);
57
+ this.emit("complete", {
58
+ affectedFilePaths: Array.from(result.affectedFileSet),
59
+ buildResults: result.buildResults
60
+ });
54
61
 
55
62
  this._debug("WATCH...");
56
63
  const fnQ = new FunctionQueue();
57
64
  const watcher = SdFsWatcher
58
- .watch(result.watchFilePaths)
65
+ .watch(Array.from(result.watchFileSet))
59
66
  .onChange({delay: 100,}, (changeInfos) => {
60
67
  this._builder!.markChanges(changeInfos.map((item) => item.path));
61
68
 
@@ -63,16 +70,19 @@ export class SdCliTsLibBuilder extends EventEmitter {
63
70
  this.emit("change");
64
71
 
65
72
  const watchResult = await this._runAsync();
66
- this.emit("complete", watchResult);
73
+ this.emit("complete", {
74
+ affectedFilePaths: Array.from(watchResult.affectedFileSet),
75
+ buildResults: watchResult.buildResults
76
+ });
67
77
 
68
- watcher.add(watchResult.watchFilePaths);
78
+ watcher.add(watchResult.watchFileSet);
69
79
  });
70
80
  });
71
81
  }
72
82
 
73
83
  private async _runAsync(): Promise<{
74
- watchFilePaths: string[];
75
- affectedFilePaths: string[];
84
+ watchFileSet: Set<string>;
85
+ affectedFileSet: Set<string>;
76
86
  buildResults: ISdCliPackageBuildResult[];
77
87
  }> {
78
88
  this._debug(`BUILD && CHECK...`);
@@ -82,23 +92,23 @@ export class SdCliTsLibBuilder extends EventEmitter {
82
92
  emitDts: true,
83
93
  globalStyle: true
84
94
  });
85
- const buildAndCheckResult = await this._builder.buildAsync();
95
+ const buildResult = await this._builder.buildAsync();
86
96
 
87
97
  this._debug("LINT...");
88
- const lintResults = await SdLinter.lintAsync(buildAndCheckResult.affectedFilePaths, this._builder.program);
98
+ const lintResults = await SdLinter.lintAsync(Array.from(buildResult.affectedFileSet).filter(item => PathUtil.isChildPath(item, this._pkgPath)), this._builder.program);
89
99
 
90
100
  this._debug(`빌드 완료`);
91
101
  const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
92
102
  .mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
93
- const watchFilePaths = buildAndCheckResult.filePaths.filter(item =>
103
+ const watchFileSet = new Set(Array.from(buildResult.watchFileSet).filter(item =>
94
104
  PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
95
105
  localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu))
96
- );
106
+ ));
97
107
 
98
108
  return {
99
- watchFilePaths,
100
- affectedFilePaths: buildAndCheckResult.affectedFilePaths,
101
- buildResults: [...buildAndCheckResult.results, ...lintResults]
109
+ watchFileSet,
110
+ affectedFileSet: buildResult.affectedFileSet,
111
+ buildResults: [...buildResult.results, ...lintResults]
102
112
  };
103
113
  }
104
114
 
@@ -146,7 +146,7 @@ export function sdNgPlugin(conf: {
146
146
  }
147
147
 
148
148
  return {
149
- name: "sd-ng",
149
+ name: "sd-ng-compiler",
150
150
  setup: (build: esbuild.PluginBuild) => {
151
151
  //-- stylesheetBundler
152
152
  const browserTarget = transformSupportedBrowsersToTargets(browserslist("defaults and fully supports es6-module"));
@@ -401,6 +401,7 @@ export function sdNgPlugin(conf: {
401
401
  conf.result.affectedFileSet = resultCache.affectedFileSet;
402
402
  conf.result.outputFiles = result.outputFiles;
403
403
  conf.result.metafile = result.metafile;
404
+ conf.result.program = ngProgram!.getTsProgram();
404
405
 
405
406
  conf.modifiedFileSet.clear();
406
407
  });
@@ -426,4 +427,5 @@ export interface INgResultCache {
426
427
  affectedFileSet?: Set<string>;
427
428
  outputFiles?: esbuild.OutputFile[];
428
429
  metafile?: esbuild.Metafile;
430
+ program?: ts.Program;
429
431
  }