@simplysm/sd-cli 12.13.13 → 12.13.15

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 (87) hide show
  1. package/dist/entry/sd-cli-electron.js +1 -1
  2. package/dist/entry/sd-cli-electron.js.map +1 -1
  3. package/dist/entry/sd-cli-project.d.ts +2 -0
  4. package/dist/entry/sd-cli-project.js +11 -3
  5. package/dist/entry/sd-cli-project.js.map +1 -1
  6. package/dist/pkg-builders/client/sd-client.build-runner.d.ts +1 -1
  7. package/dist/pkg-builders/client/sd-client.build-runner.js +74 -50
  8. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  9. package/dist/pkg-builders/client/sd-ng.bundler.d.ts +2 -0
  10. package/dist/pkg-builders/client/sd-ng.bundler.js +19 -20
  11. package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
  12. package/dist/pkg-builders/client/sd-ng.plugin-creator.d.ts +2 -0
  13. package/dist/pkg-builders/client/sd-ng.plugin-creator.js +94 -33
  14. package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
  15. package/dist/pkg-builders/commons/build-runner.base.d.ts +4 -2
  16. package/dist/pkg-builders/commons/build-runner.base.js +45 -25
  17. package/dist/pkg-builders/commons/build-runner.base.js.map +1 -1
  18. package/dist/pkg-builders/lib/sd-js-lib.build-runner.d.ts +1 -1
  19. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js +14 -4
  20. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js.map +1 -1
  21. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.d.ts +1 -1
  22. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js +21 -40
  23. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
  24. package/dist/pkg-builders/lib/sd-ts-lib.builder.d.ts +1 -1
  25. package/dist/pkg-builders/lib/sd-ts-lib.builder.js +3 -1
  26. package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
  27. package/dist/pkg-builders/sd-multi.build-runner.js +116 -86
  28. package/dist/pkg-builders/sd-multi.build-runner.js.map +1 -1
  29. package/dist/pkg-builders/server/sd-server.build-runner.d.ts +1 -1
  30. package/dist/pkg-builders/server/sd-server.build-runner.js +9 -5
  31. package/dist/pkg-builders/server/sd-server.build-runner.js.map +1 -1
  32. package/dist/pkg-builders/server/sd-server.bundler.d.ts +2 -0
  33. package/dist/pkg-builders/server/sd-server.bundler.js +3 -1
  34. package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
  35. package/dist/pkg-builders/server/sd-server.plugin-creator.d.ts +2 -0
  36. package/dist/pkg-builders/server/sd-server.plugin-creator.js +4 -1
  37. package/dist/pkg-builders/server/sd-server.plugin-creator.js.map +1 -1
  38. package/dist/sd-cli-entry.js +10 -0
  39. package/dist/sd-cli-entry.js.map +1 -1
  40. package/dist/sd-cli.js +8 -6
  41. package/dist/sd-cli.js.map +1 -1
  42. package/dist/ts-compiler/sd-dependency-analyzer.d.ts +8 -1
  43. package/dist/ts-compiler/sd-dependency-analyzer.js +128 -63
  44. package/dist/ts-compiler/sd-dependency-analyzer.js.map +1 -1
  45. package/dist/ts-compiler/sd-dependency-cache.d.ts +0 -34
  46. package/dist/ts-compiler/sd-dependency-cache.js +73 -119
  47. package/dist/ts-compiler/sd-dependency-cache.js.map +1 -1
  48. package/dist/ts-compiler/sd-style-bundler.d.ts +16 -0
  49. package/dist/ts-compiler/sd-style-bundler.js +118 -0
  50. package/dist/ts-compiler/sd-style-bundler.js.map +1 -0
  51. package/dist/ts-compiler/sd-ts-compiler.js +418 -235
  52. package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
  53. package/dist/types/build-runner.types.d.ts +2 -0
  54. package/dist/types/config.types.d.ts +2 -0
  55. package/dist/types/ts-compiler.types.d.ts +2 -0
  56. package/dist/types/worker.types.d.ts +1 -1
  57. package/dist/workers/build-runner.worker.js +1 -1
  58. package/dist/workers/build-runner.worker.js.map +1 -1
  59. package/dist/workers/server.worker.js +2 -2
  60. package/dist/workers/server.worker.js.map +1 -1
  61. package/package.json +13 -12
  62. package/src/entry/sd-cli-electron.ts +2 -1
  63. package/src/entry/sd-cli-project.ts +13 -3
  64. package/src/pkg-builders/client/sd-client.build-runner.ts +93 -54
  65. package/src/pkg-builders/client/sd-ng.bundler.ts +79 -85
  66. package/src/pkg-builders/client/sd-ng.plugin-creator.ts +119 -39
  67. package/src/pkg-builders/commons/build-runner.base.ts +78 -33
  68. package/src/pkg-builders/lib/sd-js-lib.build-runner.ts +24 -7
  69. package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +36 -42
  70. package/src/pkg-builders/lib/sd-ts-lib.builder.ts +4 -0
  71. package/src/pkg-builders/sd-multi.build-runner.ts +137 -108
  72. package/src/pkg-builders/server/sd-server.build-runner.ts +10 -4
  73. package/src/pkg-builders/server/sd-server.bundler.ts +5 -1
  74. package/src/pkg-builders/server/sd-server.plugin-creator.ts +10 -5
  75. package/src/sd-cli-entry.ts +10 -0
  76. package/src/sd-cli.ts +8 -6
  77. package/src/ts-compiler/sd-dependency-analyzer.ts +161 -86
  78. package/src/ts-compiler/sd-dependency-cache.ts +118 -99
  79. package/src/ts-compiler/sd-style-bundler.ts +150 -0
  80. package/src/ts-compiler/sd-ts-compiler.ts +559 -296
  81. package/src/types/build-runner.types.ts +2 -0
  82. package/src/types/config.types.ts +3 -0
  83. package/src/types/ts-compiler.types.ts +15 -11
  84. package/src/types/worker.types.ts +7 -10
  85. package/src/workers/build-runner.worker.ts +9 -5
  86. package/src/workers/server.worker.ts +2 -2
  87. package/tests/deps/sd-dependency-cache.spec.ts +1 -1
@@ -1,11 +1,20 @@
1
1
  import { EventEmitter } from "events";
2
- import { FsUtils, ISdFsWatcherChangeInfo, PathUtils, SdFsWatcher, SdLogger, TNormPath } from "@simplysm/sd-core-node";
2
+ import {
3
+ FsUtils,
4
+ ISdFsWatcherChangeInfo,
5
+ PathUtils,
6
+ SdFsWatcher,
7
+ SdLogger,
8
+ TNormPath,
9
+ } from "@simplysm/sd-core-node";
3
10
  import { ISdProjectConfig, TSdPackageConfig } from "../../types/config.types";
4
11
  import { ISdBuildMessage, ISdBuildRunnerResult } from "../../types/build.types";
5
12
  import path from "path";
6
13
  import { ScopePathSet } from "./scope-path";
7
14
 
8
- export abstract class BuildRunnerBase<T extends "server" | "library" | "client"> extends EventEmitter {
15
+ export abstract class BuildRunnerBase<
16
+ T extends "server" | "library" | "client",
17
+ > extends EventEmitter {
9
18
  protected abstract _logger: SdLogger;
10
19
 
11
20
  protected _pkgName: string;
@@ -24,6 +33,8 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
24
33
  projConf: ISdProjectConfig,
25
34
  protected _pkgPath: TNormPath,
26
35
  workspaceGlobs: string[],
36
+ protected _emitOnly: boolean,
37
+ protected _noEmit: boolean,
27
38
  ) {
28
39
  super();
29
40
 
@@ -31,24 +42,27 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
31
42
  this._pkgConf = projConf.packages[this._pkgName] as TSdPackageConfig<T>;
32
43
 
33
44
  const workspacePaths = workspaceGlobs
34
- .map((item) => PathUtils.posix(this._pkgPath, "../../", item))
45
+ .map((item) => PathUtils.posix(this._pkgPath, "../../", item, "src"))
35
46
  .mapMany((item) => FsUtils.glob(item));
36
- const localUpdatePaths = Object.keys(projConf.localUpdates ?? {}).mapMany((key) =>
37
- FsUtils.glob(path.resolve(this._pkgPath, "../../node_modules", key)),
38
- );
47
+ const localUpdatePaths = Object.keys(projConf.localUpdates ?? {}).mapMany((key) => [
48
+ ...FsUtils.glob(path.resolve(this._pkgPath, "../../node_modules", key, "dist")),
49
+ ...FsUtils.glob(path.resolve(this._pkgPath, "../../node_modules", key, "src/**/*.scss")),
50
+ ]);
39
51
  this._watchScopePathSet = new ScopePathSet(
40
52
  [...workspacePaths, ...localUpdatePaths].map((item) => PathUtils.norm(item)),
41
53
  );
42
54
  }
43
55
 
44
56
  async buildAsync(): Promise<ISdBuildRunnerResult> {
45
- const distPath = path.resolve(this._pkgPath, "dist");
46
- if (FsUtils.exists(distPath)) {
47
- this._debug("dist 초기화...");
48
- FsUtils.remove(distPath);
57
+ if (!this._noEmit) {
58
+ const distPath = path.resolve(this._pkgPath, "dist");
59
+ if (FsUtils.exists(distPath)) {
60
+ this._debug("dist 초기화...");
61
+ FsUtils.remove(distPath);
62
+ }
49
63
  }
50
64
 
51
- const result = await this._runAsync(false);
65
+ const result = await this._runAsync(false, false, false);
52
66
  return {
53
67
  affectedFilePathSet: result.affectedFileSet,
54
68
  buildMessages: result.buildMessages,
@@ -59,13 +73,19 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
59
73
  async watchAsync() {
60
74
  this.emit("change");
61
75
 
62
- const distPath = path.resolve(this._pkgPath, "dist");
63
- if (FsUtils.exists(distPath)) {
64
- this._debug("dist 초기화...");
65
- FsUtils.remove(distPath);
76
+ if (!this._noEmit) {
77
+ const distPath = path.resolve(this._pkgPath, "dist");
78
+ if (FsUtils.exists(distPath)) {
79
+ this._debug("dist 초기화...");
80
+ FsUtils.remove(distPath);
81
+ }
66
82
  }
67
83
 
68
- const result = await this._runAsync(!this._pkgConf.forceProductionMode);
84
+ const result = await this._runAsync(
85
+ !this._pkgConf.forceProductionMode,
86
+ this._emitOnly,
87
+ this._noEmit,
88
+ );
69
89
  const res: ISdBuildRunnerResult = {
70
90
  affectedFilePathSet: result.affectedFileSet,
71
91
  buildMessages: result.buildMessages,
@@ -77,17 +97,17 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
77
97
  let lastWatchFileSet = result.watchFileSet;
78
98
  SdFsWatcher.watch(this._watchScopePathSet.toArray(), {
79
99
  ignore: (filePath) =>
80
- filePath === path.resolve(this._pkgPath, ".cache") ||
81
- filePath === path.resolve(this._pkgPath, ".cordova") ||
82
- filePath === path.resolve(this._pkgPath, ".electron") ||
83
- filePath === path.resolve(this._pkgPath, "dist") ||
84
- (this._pkgConf.type === "client" && filePath === path.resolve(this._pkgPath, "src", "routes.ts")) ||
100
+ (this._pkgConf.type === "client" &&
101
+ path.dirname(path.basename(filePath)) === "src" &&
102
+ path.basename(filePath) === `routes.ts`) ||
85
103
  (this._pkgConf.type === "library" &&
86
104
  this._pkgConf.dbContext != null &&
87
- filePath === path.resolve(this._pkgPath, "src", `${this._pkgConf.dbContext}.ts`)) ||
105
+ path.dirname(path.basename(filePath)) === "src" &&
106
+ path.basename(filePath) === `${this._pkgConf.dbContext}.ts`) ||
88
107
  (this._pkgConf.type === "library" &&
89
108
  !this._pkgConf.noGenIndex &&
90
- filePath === path.resolve(this._pkgPath, "src", "index.ts")),
109
+ path.dirname(path.basename(filePath)) === "src" &&
110
+ path.basename(filePath) === "index.ts"),
91
111
  }).onChange({ delay: 100 }, async (changeInfos) => {
92
112
  const modifiedFileSet = this._getModifiedFileSet(changeInfos, lastWatchFileSet);
93
113
 
@@ -97,7 +117,12 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
97
117
 
98
118
  let watchResult: IBuildRunnerRunResult;
99
119
  try {
100
- watchResult = await this._runAsync(!this._pkgConf.forceProductionMode, modifiedFileSet);
120
+ watchResult = await this._runAsync(
121
+ !this._pkgConf.forceProductionMode,
122
+ this._emitOnly,
123
+ this._noEmit,
124
+ modifiedFileSet,
125
+ );
101
126
 
102
127
  lastWatchFileSet = watchResult.watchFileSet;
103
128
  } catch (err) {
@@ -126,18 +151,38 @@ export abstract class BuildRunnerBase<T extends "server" | "library" | "client">
126
151
  });
127
152
  }
128
153
 
129
- protected _getModifiedFileSet(changeInfos: ISdFsWatcherChangeInfo[], lastWatchFileSet?: Set<TNormPath>) {
130
- return new Set(
131
- (lastWatchFileSet
132
- ? changeInfos.filter((item) =>
133
- Array.from(lastWatchFileSet).some((item1) => item.path.startsWith(path.dirname(item1))),
154
+ protected _getModifiedFileSet(
155
+ changeInfos: ISdFsWatcherChangeInfo[],
156
+ lastWatchFileSet?: Set<TNormPath>,
157
+ ) {
158
+ if (!lastWatchFileSet) {
159
+ return new Set(changeInfos.map((item) => item.path));
160
+ } else {
161
+ return new Set(
162
+ changeInfos
163
+ .filter(
164
+ (item) =>
165
+ Array.from(lastWatchFileSet).some((item1) =>
166
+ item.path.startsWith(path.dirname(item1)),
167
+ ) ||
168
+ ((this._pkgConf.type === "client" ||
169
+ (this._pkgConf.type === "library" && this._pkgConf.dbContext != null) ||
170
+ (this._pkgConf.type === "library" && this._pkgConf.noGenIndex)) &&
171
+ item.path.startsWith(path.resolve(this._pkgPath, "src")) &&
172
+ item.path.endsWith(".ts") &&
173
+ item.event === "add"),
134
174
  )
135
- : changeInfos
136
- ).map((item) => item.path),
137
- );
175
+ .map((item) => item.path),
176
+ );
177
+ }
138
178
  }
139
179
 
140
- protected abstract _runAsync(dev: boolean, modifiedFileSet?: Set<TNormPath>): Promise<IBuildRunnerRunResult>;
180
+ protected abstract _runAsync(
181
+ dev: boolean,
182
+ emitOnly: boolean,
183
+ noEmit: boolean,
184
+ modifiedFileSet?: Set<TNormPath>,
185
+ ): Promise<IBuildRunnerRunResult>;
141
186
 
142
187
  protected _debug(msg: string): void {
143
188
  this._logger.debug(`[${path.basename(this._pkgPath)}] ${msg}`);
@@ -16,11 +16,25 @@ export class SdJsLibBuildRunner extends BuildRunnerBase<"library"> {
16
16
 
17
17
  protected override async _runAsync(
18
18
  dev: boolean,
19
+ emitOnly: boolean,
20
+ noEmit: boolean,
19
21
  modifiedFileSet?: Set<TNormPath>,
20
22
  ): Promise<IBuildRunnerRunResult> {
21
- const filePathSet = modifiedFileSet ?? new Set(
22
- FsUtils.glob(path.resolve(this._pkgPath, "src/**/*.js")).map(item => PathUtils.norm(item)),
23
- );
23
+ if (emitOnly) {
24
+ return {
25
+ affectedFileSet: new Set(),
26
+ buildMessages: [],
27
+ emitFileSet: new Set(),
28
+ };
29
+ }
30
+
31
+ const filePathSet =
32
+ modifiedFileSet ??
33
+ new Set(
34
+ FsUtils.glob(path.resolve(this._pkgPath, "src/**/*.js")).map((item) =>
35
+ PathUtils.norm(item),
36
+ ),
37
+ );
24
38
 
25
39
  this._debug("LINT...");
26
40
 
@@ -38,10 +52,13 @@ export class SdJsLibBuildRunner extends BuildRunnerBase<"library"> {
38
52
 
39
53
  protected override _getModifiedFileSet(changeInfos: ISdFsWatcherChangeInfo[]) {
40
54
  return new Set(
41
- changeInfos.filter((item) =>
42
- FsUtils.exists(item.path)
43
- && PathUtils.isChildPath(item.path, path.resolve(this._pkgPath, "src")),
44
- ).map(item => item.path),
55
+ changeInfos
56
+ .filter(
57
+ (item) =>
58
+ FsUtils.exists(item.path) &&
59
+ PathUtils.isChildPath(item.path, path.resolve(this._pkgPath, "src")),
60
+ )
61
+ .map((item) => item.path),
45
62
  );
46
63
  }
47
64
 
@@ -14,59 +14,53 @@ export class SdTsLibBuildRunner extends BuildRunnerBase<"library"> {
14
14
  #hasGenIndexError = false;
15
15
  #hasGenDbContextError = false;
16
16
 
17
- protected override async _runAsync(dev: boolean, modifiedFileSet?: Set<TNormPath>): Promise<IBuildRunnerRunResult> {
18
- /*if (!modifiedFileSet) {
19
- if (!dev) {
20
- if (!this._pkgConf.noGenIndex) {
21
- this._debug("GEN index.ts...");
22
- this.#indexFileGenerator.run(this._pkgPath, this._pkgConf.polyfills);
23
- }
24
-
25
- if (this._pkgConf.dbContext != null) {
26
- this._debug(`GEN ${this._pkgConf.dbContext}.ts...`);
27
- this.#dbContextGenerator.run(this._pkgPath, this._pkgConf.dbContext);
28
- }
29
- } else {
30
- if (!this._pkgConf.noGenIndex) {
31
- this._debug("Watch for GEN index.ts...");
32
- this.#indexFileGenerator.watch(this._pkgPath, this._pkgConf.polyfills);
33
- }
34
-
35
- if (this._pkgConf.dbContext != null) {
36
- this._debug(`Watch for GEN ${this._pkgConf.dbContext}.ts...`);
37
- this.#dbContextGenerator.watch(this._pkgPath, this._pkgConf.dbContext);
38
- }
39
- }
40
- }*/
41
-
17
+ protected override async _runAsync(
18
+ dev: boolean,
19
+ emitOnly: boolean,
20
+ noEmit: boolean,
21
+ modifiedFileSet?: Set<TNormPath>,
22
+ ): Promise<IBuildRunnerRunResult> {
42
23
  let indexFileNPath: TNormPath | undefined;
43
- if (!this._pkgConf.noGenIndex) {
44
- this._debug("GEN index.ts...");
45
- const genIndexResult = this.#indexFileGenerator.run(this._pkgPath, this._pkgConf.polyfills);
46
- if (modifiedFileSet && (genIndexResult.changed || this.#hasGenIndexError)) {
47
- modifiedFileSet.add(PathUtils.norm(genIndexResult.filePath));
24
+ let dbContentFileNPath: TNormPath | undefined;
25
+ if (!noEmit) {
26
+ if (!this._pkgConf.noGenIndex) {
27
+ this._debug("GEN index.ts...");
28
+ const genIndexResult = this.#indexFileGenerator.run(this._pkgPath, this._pkgConf.polyfills);
29
+ if (modifiedFileSet && (genIndexResult.changed || this.#hasGenIndexError)) {
30
+ modifiedFileSet.add(PathUtils.norm(genIndexResult.filePath));
31
+ }
32
+ indexFileNPath = PathUtils.norm(genIndexResult.filePath);
48
33
  }
49
- indexFileNPath = PathUtils.norm(genIndexResult.filePath);
50
- }
51
34
 
52
- let dbContentFileNPath: TNormPath | undefined;
53
- if (this._pkgConf.dbContext != null) {
54
- this._debug(`GEN ${this._pkgConf.dbContext}.ts...`);
55
- const genDbContextResult = this.#dbContextGenerator.run(this._pkgPath, this._pkgConf.dbContext);
56
- if (modifiedFileSet && (genDbContextResult.changed || this.#hasGenDbContextError)) {
57
- modifiedFileSet.add(PathUtils.norm(genDbContextResult.filePath));
35
+ if (this._pkgConf.dbContext != null) {
36
+ this._debug(`GEN ${this._pkgConf.dbContext}.ts...`);
37
+ const genDbContextResult = this.#dbContextGenerator.run(
38
+ this._pkgPath,
39
+ this._pkgConf.dbContext,
40
+ );
41
+ if (modifiedFileSet && (genDbContextResult.changed || this.#hasGenDbContextError)) {
42
+ modifiedFileSet.add(PathUtils.norm(genDbContextResult.filePath));
43
+ }
44
+ dbContentFileNPath = PathUtils.norm(genDbContextResult.filePath);
58
45
  }
59
- dbContentFileNPath = PathUtils.norm(genDbContextResult.filePath);
60
46
  }
61
47
 
62
48
  this._debug(`BUILD...`);
63
- this.#builder ??= new SdTsLibBuilder(PathUtils.norm(this._pkgPath), dev, this._watchScopePathSet);
49
+ this.#builder ??= new SdTsLibBuilder(
50
+ PathUtils.norm(this._pkgPath),
51
+ dev,
52
+ emitOnly,
53
+ noEmit,
54
+ this._watchScopePathSet,
55
+ );
64
56
  const buildResult = await this.#builder.buildAsync(modifiedFileSet ?? new Set());
65
57
 
66
58
  this.#hasGenIndexError =
67
- indexFileNPath != null && buildResult.results.map((item) => item.filePath).includes(indexFileNPath);
59
+ indexFileNPath != null &&
60
+ buildResult.results.map((item) => item.filePath).includes(indexFileNPath);
68
61
  this.#hasGenDbContextError =
69
- dbContentFileNPath != null && buildResult.results.map((item) => item.filePath).includes(dbContentFileNPath);
62
+ dbContentFileNPath != null &&
63
+ buildResult.results.map((item) => item.filePath).includes(dbContentFileNPath);
70
64
 
71
65
  this._debug(`빌드 완료`);
72
66
  const watchFileSet = new Set(
@@ -12,12 +12,16 @@ export class SdTsLibBuilder {
12
12
  constructor(
13
13
  private readonly _pkgPath: TNormPath,
14
14
  dev: boolean,
15
+ emitOnly: boolean,
16
+ noEmit: boolean,
15
17
  watchScopePathSet: ScopePathSet,
16
18
  ) {
17
19
  this.#tsCompiler = new SdTsCompiler({
18
20
  pkgPath: this._pkgPath,
19
21
  additionalOptions: { declaration: true },
20
22
  isDevMode: dev,
23
+ isEmitOnly: emitOnly,
24
+ isNoEmit: noEmit,
21
25
  globalStyleFilePath: PathUtils.norm(this._pkgPath, "src/styles.scss"),
22
26
  isForBundle: false,
23
27
  watchScopePathSet,
@@ -20,6 +20,8 @@ export class SdMultiBuildRunner extends EventEmitter {
20
20
  worker?: SdWorker<TServerWorkerType>; // persist
21
21
  port?: number; // run server result
22
22
  hasChanges: boolean;
23
+
24
+ clientPath?: string;
23
25
  clientChangedFileSet: Set<string>;
24
26
 
25
27
  // from client
@@ -28,6 +30,7 @@ export class SdMultiBuildRunner extends EventEmitter {
28
30
  {
29
31
  buildTypes: ("web" | "electron" | "cordova")[];
30
32
  path: string;
33
+ changedFileSet: Set<string>;
31
34
  }
32
35
  >; // persist
33
36
  }
@@ -43,8 +46,9 @@ export class SdMultiBuildRunner extends EventEmitter {
43
46
  async runAsync(req: ISdBuildRunnerWorkerRequest & { cmd: "watch" }): Promise<void>;
44
47
  async runAsync(req: ISdBuildRunnerWorkerRequest & { cmd: "build" }): Promise<ISdBuildMessage[]>;
45
48
  async runAsync(req: ISdBuildRunnerWorkerRequest): Promise<ISdBuildMessage[] | void> {
46
- const worker = new SdWorker<TSdBuildRunnerWorkerType>(import.meta.resolve(
47
- "../workers/build-runner.worker"))
49
+ const worker = new SdWorker<TSdBuildRunnerWorkerType>(
50
+ import.meta.resolve("../workers/build-runner.worker"),
51
+ )
48
52
  .on("change", () => {
49
53
  if (this.#busyCount === 0) {
50
54
  this.emit("change");
@@ -81,135 +85,161 @@ export class SdMultiBuildRunner extends EventEmitter {
81
85
  #onComplete(req: ISdBuildRunnerWorkerRequest, result: ISdBuildRunnerResult) {
82
86
  this.#resultCache.delete(req.pkgPath);
83
87
  for (const affectedFilePath of result.affectedFilePathSet) {
84
- if (PathUtils.isChildPath(affectedFilePath, req.pkgPath)) {
85
- this.#resultCache.delete(affectedFilePath);
86
- }
88
+ this.#resultCache.delete(affectedFilePath);
87
89
  }
88
90
 
89
91
  for (const buildMessage of result.buildMessages) {
90
- const cacheItem = this.#resultCache.getOrCreate(buildMessage.filePath ?? req.pkgPath, []);
91
- cacheItem.push(buildMessage);
92
+ if (!buildMessage.filePath || PathUtils.isChildPath(buildMessage.filePath, req.pkgPath)) {
93
+ const cacheItem = this.#resultCache.getOrCreate(buildMessage.filePath ?? req.pkgPath, []);
94
+ cacheItem.push(buildMessage);
95
+ }
92
96
  }
93
97
 
94
- const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
98
+ if (req.noEmit) {
99
+ setTimeout(() => {
100
+ this.#busyCount--;
101
+ if (this.#busyCount === 0) {
102
+ const messages = Array.from(this.#resultCache.values()).mapMany();
103
+ this.emit("complete", messages);
104
+ }
105
+ }, 300);
106
+ } else {
107
+ const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
95
108
 
96
- if (pkgConf.type === "server") {
97
- const pkgName = path.basename(req.pkgPath);
98
- const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
99
- hasChanges: true,
100
- clientChangedFileSet: new Set(),
101
- clients: {},
102
- });
109
+ if (pkgConf.type === "server") {
110
+ const pkgName = path.basename(req.pkgPath);
111
+ const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
112
+ hasChanges: true,
113
+ clientChangedFileSet: new Set(),
114
+ clients: {},
115
+ });
103
116
 
104
- const serverPkgConf = req.projConf.packages[pkgName] as ISdServerPackageConfig;
105
- serverInfo.pkgInfo = {
106
- path: req.pkgPath,
107
- conf: serverPkgConf,
108
- };
117
+ const serverPkgConf = req.projConf.packages[pkgName] as ISdServerPackageConfig;
118
+ serverInfo.pkgInfo = {
119
+ path: req.pkgPath,
120
+ conf: serverPkgConf,
121
+ };
109
122
 
110
- serverInfo.hasChanges = true;
111
- }
112
- else if (pkgConf.type === "client") {
113
- const pkgName = path.basename(req.pkgPath);
123
+ serverInfo.hasChanges = true;
124
+ } else if (pkgConf.type === "client") {
125
+ const pkgName = path.basename(req.pkgPath);
126
+
127
+ if (pkgConf.server != null) {
128
+ const serverInfo = this.#serverInfoMap.getOrCreate(
129
+ typeof pkgConf.server === "string" ? pkgConf.server : pkgConf.server.port.toString(),
130
+ {
131
+ hasChanges: true,
132
+ clientChangedFileSet: new Set(),
133
+ clients: {},
134
+ },
135
+ );
136
+
137
+ if (typeof pkgConf.server !== "string") {
138
+ serverInfo.pkgInfo = pkgConf.server;
139
+ }
114
140
 
115
- if (pkgConf.server !== undefined) {
116
- const serverInfo = this.#serverInfoMap.getOrCreate(
117
- typeof pkgConf.server === "string" ? pkgConf.server : pkgConf.server.port.toString(),
118
- {
141
+ serverInfo.clients[pkgName] = {
142
+ path: path.resolve(req.pkgPath, "dist"),
143
+ buildTypes: (pkgConf.builder ? Object.keys(pkgConf.builder) : ["web"]) as any,
144
+ changedFileSet: result.emitFileSet,
145
+ };
146
+ } else {
147
+ const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
119
148
  hasChanges: true,
149
+ clientPath: path.resolve(req.pkgPath, "dist"),
120
150
  clientChangedFileSet: new Set(),
121
151
  clients: {},
122
- },
123
- );
152
+ });
124
153
 
125
- if (typeof pkgConf.server !== "string") {
126
- serverInfo.pkgInfo = pkgConf.server;
154
+ serverInfo.clientChangedFileSet = result.emitFileSet;
127
155
  }
128
-
129
- serverInfo.clients[pkgName] = {
130
- path: path.resolve(req.pkgPath, "dist"),
131
- buildTypes: (pkgConf.builder ? Object.keys(pkgConf.builder) : ["web"]) as any,
132
- };
133
-
134
- serverInfo.clientChangedFileSet.adds(...result.emitFileSet);
135
- }
136
- else {
137
- const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
138
- hasChanges: true,
139
- clientChangedFileSet: new Set(),
140
- clients: {},
141
- });
142
-
143
- serverInfo.clientChangedFileSet.adds(...result.emitFileSet);
144
156
  }
145
- }
146
157
 
147
- setTimeout(async () => {
148
- this.#busyCount--;
149
- if (this.#busyCount === 0) {
150
- for (const serverPkgNameOrPort of this.#serverInfoMap.keys()) {
151
- const serverInfo = this.#serverInfoMap.get(serverPkgNameOrPort)!;
152
- if (serverInfo.pkgInfo && serverInfo.hasChanges) {
153
- this.#logger.debug("서버 재시작...");
154
- try {
155
- const restartServerResult = await this.#restartServerAsync(
156
- serverInfo.pkgInfo,
157
- serverInfo.worker,
158
- );
159
- serverInfo.worker = restartServerResult.worker;
160
- serverInfo.port = restartServerResult.port;
161
- serverInfo.hasChanges = false;
162
- }
163
- catch (err) {
164
- this.#logger.error(err);
158
+ setTimeout(async () => {
159
+ this.#busyCount--;
160
+ if (this.#busyCount === 0) {
161
+ for (const serverPkgNameOrPort of this.#serverInfoMap.keys()) {
162
+ const serverInfo = this.#serverInfoMap.get(serverPkgNameOrPort)!;
163
+ if (serverInfo.pkgInfo && serverInfo.hasChanges) {
164
+ this.#logger.debug("서버 재시작...");
165
+ try {
166
+ const restartServerResult = await this.#restartServerAsync(
167
+ serverInfo.pkgInfo,
168
+ serverInfo.worker,
169
+ );
170
+ serverInfo.worker = restartServerResult.worker;
171
+ serverInfo.port = restartServerResult.port;
172
+ serverInfo.hasChanges = false;
173
+ } catch (err) {
174
+ this.#logger.error(err);
175
+ }
165
176
  }
166
- }
167
177
 
168
- if (serverInfo.worker) {
169
- this.#logger.debug("클라이언트 설정...");
170
- await serverInfo.worker.run("setPathProxy", [
171
- {
172
- ...Object.keys(serverInfo.clients).toObject(
173
- (key) => key,
174
- (key) => serverInfo.clients[key].path,
175
- ),
176
- node_modules: path.resolve(process.cwd(), "node_modules"),
177
- },
178
- ]);
179
-
180
- if (serverInfo.clientChangedFileSet.size > 0) {
181
- this.#logger.debug("클라이언트 새로고침...");
182
- await serverInfo.worker.run("broadcastReload", [serverInfo.clientChangedFileSet]);
178
+ if (serverInfo.worker) {
179
+ this.#logger.debug("클라이언트 설정...");
180
+ await serverInfo.worker.run("setPathProxy", [
181
+ {
182
+ ...Object.keys(serverInfo.clients).toObject(
183
+ (key) => key,
184
+ (key) => serverInfo.clients[key].path,
185
+ ),
186
+ node_modules: path.resolve(process.cwd(), "node_modules"),
187
+ },
188
+ ]);
189
+
190
+ if (Object.keys(serverInfo.clients).length > 0) {
191
+ for (const clientName of Object.keys(serverInfo.clients)) {
192
+ this.#logger.debug(`${clientName} 클라이언트 새로고침...`);
193
+ await serverInfo.worker.run("broadcastReload", [
194
+ clientName,
195
+ new Set(
196
+ Array.from(serverInfo.clients[clientName].changedFileSet)
197
+ .filter((item) => !item.endsWith(".map"))
198
+ .map((item) => path.relative(serverInfo.clients[clientName].path, item)),
199
+ ),
200
+ ]);
201
+ }
202
+ } else if (serverInfo.clientChangedFileSet.size > 0) {
203
+ this.#logger.debug("클라이언트 새로고침...");
204
+ await serverInfo.worker.run("broadcastReload", [
205
+ undefined,
206
+ new Set(
207
+ Array.from(serverInfo.clientChangedFileSet)
208
+ .filter((item) => !item.endsWith(".map"))
209
+ .map((item) => path.relative(serverInfo.clientPath!, item)),
210
+ ),
211
+ ]);
212
+ }
183
213
  }
184
214
  }
185
- }
186
215
 
187
- const clientPaths: string[] = [];
188
- for (const serverInfo of this.#serverInfoMap.values()) {
189
- if (Object.keys(serverInfo.clients).length > 0) {
190
- for (const clientPkgName of Object.keys(serverInfo.clients)) {
191
- for (const buildType of serverInfo.clients[clientPkgName].buildTypes) {
192
- if (buildType === "web") {
193
- clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/`);
194
- }
195
- else {
196
- clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/${buildType}/`);
216
+ const clientPaths: string[] = [];
217
+ for (const serverInfo of this.#serverInfoMap.values()) {
218
+ if (Object.keys(serverInfo.clients).length > 0) {
219
+ for (const clientPkgName of Object.keys(serverInfo.clients)) {
220
+ for (const buildType of serverInfo.clients[clientPkgName].buildTypes) {
221
+ if (buildType === "web") {
222
+ clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/`);
223
+ } else {
224
+ clientPaths.push(
225
+ `http://localhost:${serverInfo.port}/${clientPkgName}/${buildType}/`,
226
+ );
227
+ }
197
228
  }
198
229
  }
230
+ } else {
231
+ clientPaths.push(`http://localhost:${serverInfo.port}/`);
199
232
  }
200
233
  }
201
- else {
202
- clientPaths.push(`http://localhost:${serverInfo.port}/`);
234
+ if (clientPaths.length > 0) {
235
+ this.#logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
203
236
  }
204
- }
205
- if (clientPaths.length > 0) {
206
- this.#logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
207
- }
208
237
 
209
- const messages = Array.from(this.#resultCache.values()).mapMany();
210
- this.emit("complete", messages);
211
- }
212
- }, 300);
238
+ const messages = Array.from(this.#resultCache.values()).mapMany();
239
+ this.emit("complete", messages);
240
+ }
241
+ }, 300);
242
+ }
213
243
  }
214
244
 
215
245
  async #restartServerAsync(
@@ -231,10 +261,9 @@ export class SdMultiBuildRunner extends EventEmitter {
231
261
  }
232
262
 
233
263
  const npmConf =
234
- "path" in pkgInfo ? (FsUtils.readJson(path.resolve(
235
- pkgInfo.path,
236
- "package.json",
237
- )) as INpmConfig) : undefined;
264
+ "path" in pkgInfo
265
+ ? (FsUtils.readJson(path.resolve(pkgInfo.path, "package.json")) as INpmConfig)
266
+ : undefined;
238
267
 
239
268
  const worker = new SdWorker<TServerWorkerType>(
240
269
  import.meta.resolve("../workers/server.worker"),