@simplysm/sd-cli 12.5.20 → 12.5.22

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 (183) hide show
  1. package/dist/{build-tools → entry}/SdCliCordova.d.ts +5 -6
  2. package/dist/{build-tools → entry}/SdCliCordova.js +117 -99
  3. package/dist/entry/SdCliCordova.js.map +1 -0
  4. package/dist/entry/SdCliElectron.d.ts +2 -2
  5. package/dist/entry/SdCliElectron.js +50 -40
  6. package/dist/entry/SdCliElectron.js.map +1 -1
  7. package/dist/entry/SdCliLocalUpdate.d.ts +1 -2
  8. package/dist/entry/SdCliLocalUpdate.js +26 -27
  9. package/dist/entry/SdCliLocalUpdate.js.map +1 -1
  10. package/dist/entry/SdCliProject.d.ts +1 -5
  11. package/dist/entry/SdCliProject.js +62 -288
  12. package/dist/entry/SdCliProject.js.map +1 -1
  13. package/dist/index.d.ts +23 -17
  14. package/dist/index.js +23 -17
  15. package/dist/index.js.map +1 -1
  16. package/dist/pkg-builders/SdMultiBuildRunner.d.ts +21 -0
  17. package/dist/pkg-builders/SdMultiBuildRunner.js +174 -0
  18. package/dist/pkg-builders/SdMultiBuildRunner.js.map +1 -0
  19. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.d.ts +4 -0
  20. package/dist/{build-tools → pkg-builders/client}/SdCliNgRoutesFileGenerator.js +7 -7
  21. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.js.map +1 -0
  22. package/dist/pkg-builders/client/SdClientBuildRunner.d.ts +20 -0
  23. package/dist/pkg-builders/client/SdClientBuildRunner.js +135 -0
  24. package/dist/pkg-builders/client/SdClientBuildRunner.js.map +1 -0
  25. package/dist/pkg-builders/client/SdNgBundler.d.ts +29 -0
  26. package/dist/{build-tools → pkg-builders/client}/SdNgBundler.js +100 -95
  27. package/dist/pkg-builders/client/SdNgBundler.js.map +1 -0
  28. package/dist/{build-tools → pkg-builders/client}/SdNgBundlerContext.d.ts +1 -2
  29. package/dist/{build-tools → pkg-builders/client}/SdNgBundlerContext.js +19 -45
  30. package/dist/pkg-builders/client/SdNgBundlerContext.js.map +1 -0
  31. package/dist/pkg-builders/client/createSdNgPlugin.d.ts +10 -0
  32. package/dist/{bundle-plugins/sdNgPlugin.js → pkg-builders/client/createSdNgPlugin.js} +32 -33
  33. package/dist/pkg-builders/client/createSdNgPlugin.js.map +1 -0
  34. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.d.ts +5 -0
  35. package/dist/{build-tools → pkg-builders/lib}/SdCliIndexFileGenerator.js +11 -11
  36. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.js.map +1 -0
  37. package/dist/pkg-builders/lib/SdJsLibBuildRunner.d.ts +16 -0
  38. package/dist/pkg-builders/lib/SdJsLibBuildRunner.js +81 -0
  39. package/dist/pkg-builders/lib/SdJsLibBuildRunner.js.map +1 -0
  40. package/dist/pkg-builders/lib/SdTsLibBuildRunner.d.ts +13 -0
  41. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js +89 -0
  42. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js.map +1 -0
  43. package/dist/pkg-builders/lib/SdTsLibBuilder.d.ts +14 -0
  44. package/dist/pkg-builders/lib/SdTsLibBuilder.js +54 -0
  45. package/dist/pkg-builders/lib/SdTsLibBuilder.js.map +1 -0
  46. package/dist/pkg-builders/server/SdServerBuildRunner.d.ts +17 -0
  47. package/dist/{builders/SdCliServerBuilder.js → pkg-builders/server/SdServerBuildRunner.js} +48 -53
  48. package/dist/pkg-builders/server/SdServerBuildRunner.js.map +1 -0
  49. package/dist/pkg-builders/server/SdServerBundler.d.ts +19 -0
  50. package/dist/{build-tools → pkg-builders/server}/SdServerBundler.js +25 -30
  51. package/dist/pkg-builders/server/SdServerBundler.js.map +1 -0
  52. package/dist/pkg-builders/server/createSdServerPlugin.d.ts +10 -0
  53. package/dist/pkg-builders/server/createSdServerPlugin.js +53 -0
  54. package/dist/pkg-builders/server/createSdServerPlugin.js.map +1 -0
  55. package/dist/sd-cli.js +61 -54
  56. package/dist/sd-cli.js.map +1 -1
  57. package/dist/ts-builder/SdTsCompileWorker.d.ts +9 -0
  58. package/dist/ts-builder/SdTsCompileWorker.js +16 -0
  59. package/dist/ts-builder/SdTsCompileWorker.js.map +1 -0
  60. package/dist/ts-builder/SdTsCompiler.d.ts +7 -0
  61. package/dist/{build-tools → ts-builder}/SdTsCompiler.js +226 -212
  62. package/dist/ts-builder/SdTsCompiler.js.map +1 -0
  63. package/dist/types/build-plugin.type.d.ts +14 -0
  64. package/dist/types/build-plugin.type.js +2 -0
  65. package/dist/types/build-plugin.type.js.map +1 -0
  66. package/dist/types/build.type.d.ts +15 -0
  67. package/dist/types/build.type.js +2 -0
  68. package/dist/types/build.type.js.map +1 -0
  69. package/dist/types/common-configs.type.d.ts +22 -0
  70. package/dist/types/common-configs.type.js +2 -0
  71. package/dist/types/common-configs.type.js.map +1 -0
  72. package/dist/types/sd-configs.type.d.ts +99 -0
  73. package/dist/types/sd-configs.type.js +2 -0
  74. package/dist/types/sd-configs.type.js.map +1 -0
  75. package/dist/types/ts-compiler.type.d.ts +29 -0
  76. package/dist/types/ts-compiler.type.js +2 -0
  77. package/dist/types/ts-compiler.type.js.map +1 -0
  78. package/dist/types/workers.type.d.ts +49 -0
  79. package/dist/types/workers.type.js +2 -0
  80. package/dist/types/workers.type.js.map +1 -0
  81. package/dist/utils/SdCliConvertMessageUtil.d.ts +21 -0
  82. package/dist/utils/SdCliConvertMessageUtil.js +137 -0
  83. package/dist/utils/SdCliConvertMessageUtil.js.map +1 -0
  84. package/dist/workers/compile-worker.js +27 -0
  85. package/dist/workers/compile-worker.js.map +1 -0
  86. package/dist/workers/lint-worker.js +36 -0
  87. package/dist/workers/lint-worker.js.map +1 -0
  88. package/dist/workers/server-worker.d.ts +1 -0
  89. package/dist/workers/server-worker.js +49 -0
  90. package/dist/workers/server-worker.js.map +1 -0
  91. package/lib/dev-worker.cjs +5 -0
  92. package/package.json +7 -7
  93. package/src/entry/SdCliCordova.ts +363 -0
  94. package/src/entry/SdCliElectron.ts +96 -69
  95. package/src/entry/SdCliLocalUpdate.ts +43 -44
  96. package/src/entry/SdCliProject.ts +72 -417
  97. package/src/index.ts +23 -17
  98. package/src/pkg-builders/SdMultiBuildRunner.ts +250 -0
  99. package/src/{build-tools → pkg-builders/client}/SdCliNgRoutesFileGenerator.ts +7 -7
  100. package/src/pkg-builders/client/SdClientBuildRunner.ts +191 -0
  101. package/src/{build-tools → pkg-builders/client}/SdNgBundler.ts +125 -121
  102. package/src/pkg-builders/client/SdNgBundlerContext.ts +111 -0
  103. package/src/{bundle-plugins/sdNgPlugin.ts → pkg-builders/client/createSdNgPlugin.ts} +43 -46
  104. package/src/{build-tools → pkg-builders/lib}/SdCliIndexFileGenerator.ts +11 -11
  105. package/src/pkg-builders/lib/SdJsLibBuildRunner.ts +105 -0
  106. package/src/pkg-builders/lib/SdTsLibBuildRunner.ts +128 -0
  107. package/src/pkg-builders/lib/SdTsLibBuilder.ts +69 -0
  108. package/src/{builders/SdCliServerBuilder.ts → pkg-builders/server/SdServerBuildRunner.ts} +66 -78
  109. package/src/{build-tools → pkg-builders/server}/SdServerBundler.ts +40 -41
  110. package/src/pkg-builders/server/createSdServerPlugin.ts +77 -0
  111. package/src/sd-cli.ts +197 -211
  112. package/src/ts-builder/SdTsCompileWorker.ts +21 -0
  113. package/src/ts-builder/SdTsCompiler.ts +758 -0
  114. package/src/types/build-plugin.type.ts +16 -0
  115. package/src/types/build.type.ts +17 -0
  116. package/src/types/common-configs.type.ts +27 -0
  117. package/src/types/sd-configs.type.ts +114 -0
  118. package/src/types/ts-compiler.type.ts +29 -0
  119. package/src/types/workers.type.ts +27 -0
  120. package/src/utils/SdCliConvertMessageUtil.ts +177 -0
  121. package/src/workers/compile-worker.ts +31 -0
  122. package/src/workers/lint-worker.ts +44 -0
  123. package/src/workers/server-worker.ts +52 -0
  124. package/tsconfig.json +7 -1
  125. package/dist/build-cluster.js +0 -201
  126. package/dist/build-cluster.js.map +0 -1
  127. package/dist/build-tools/SdCliCordova.js.map +0 -1
  128. package/dist/build-tools/SdCliIndexFileGenerator.d.ts +0 -5
  129. package/dist/build-tools/SdCliIndexFileGenerator.js.map +0 -1
  130. package/dist/build-tools/SdCliNgRoutesFileGenerator.d.ts +0 -4
  131. package/dist/build-tools/SdCliNgRoutesFileGenerator.js.map +0 -1
  132. package/dist/build-tools/SdLinter.d.ts +0 -5
  133. package/dist/build-tools/SdLinter.js +0 -49
  134. package/dist/build-tools/SdLinter.js.map +0 -1
  135. package/dist/build-tools/SdNgBundler.d.ts +0 -29
  136. package/dist/build-tools/SdNgBundler.js.map +0 -1
  137. package/dist/build-tools/SdNgBundlerContext.js.map +0 -1
  138. package/dist/build-tools/SdServerBundler.d.ts +0 -20
  139. package/dist/build-tools/SdServerBundler.js.map +0 -1
  140. package/dist/build-tools/SdTsCompiler.d.ts +0 -34
  141. package/dist/build-tools/SdTsCompiler.js.map +0 -1
  142. package/dist/build-tools/SdTsLibBundler.d.ts +0 -13
  143. package/dist/build-tools/SdTsLibBundler.js +0 -58
  144. package/dist/build-tools/SdTsLibBundler.js.map +0 -1
  145. package/dist/builders/SdCliClientBuilder.d.ts +0 -18
  146. package/dist/builders/SdCliClientBuilder.js +0 -151
  147. package/dist/builders/SdCliClientBuilder.js.map +0 -1
  148. package/dist/builders/SdCliJsLibLinter.d.ts +0 -13
  149. package/dist/builders/SdCliJsLibLinter.js +0 -60
  150. package/dist/builders/SdCliJsLibLinter.js.map +0 -1
  151. package/dist/builders/SdCliServerBuilder.d.ts +0 -15
  152. package/dist/builders/SdCliServerBuilder.js.map +0 -1
  153. package/dist/builders/SdCliTsLibBuilder.d.ts +0 -12
  154. package/dist/builders/SdCliTsLibBuilder.js +0 -90
  155. package/dist/builders/SdCliTsLibBuilder.js.map +0 -1
  156. package/dist/bundle-plugins/sdNgPlugin.d.ts +0 -16
  157. package/dist/bundle-plugins/sdNgPlugin.js.map +0 -1
  158. package/dist/bundle-plugins/sdServerPlugin.d.ts +0 -16
  159. package/dist/bundle-plugins/sdServerPlugin.js +0 -63
  160. package/dist/bundle-plugins/sdServerPlugin.js.map +0 -1
  161. package/dist/commons.d.ts +0 -145
  162. package/dist/commons.js +0 -2
  163. package/dist/commons.js.map +0 -1
  164. package/dist/server-worker.js +0 -57
  165. package/dist/server-worker.js.map +0 -1
  166. package/dist/utils/SdCliBuildResultUtil.d.ts +0 -16
  167. package/dist/utils/SdCliBuildResultUtil.js +0 -54
  168. package/dist/utils/SdCliBuildResultUtil.js.map +0 -1
  169. package/src/build-cluster.ts +0 -212
  170. package/src/build-tools/SdCliCordova.ts +0 -340
  171. package/src/build-tools/SdLinter.ts +0 -65
  172. package/src/build-tools/SdNgBundlerContext.ts +0 -137
  173. package/src/build-tools/SdTsCompiler.ts +0 -754
  174. package/src/build-tools/SdTsLibBundler.ts +0 -72
  175. package/src/builders/SdCliClientBuilder.ts +0 -211
  176. package/src/builders/SdCliJsLibLinter.ts +0 -72
  177. package/src/builders/SdCliTsLibBuilder.ts +0 -126
  178. package/src/bundle-plugins/sdServerPlugin.ts +0 -94
  179. package/src/commons.ts +0 -171
  180. package/src/server-worker.ts +0 -65
  181. package/src/utils/SdCliBuildResultUtil.ts +0 -63
  182. /package/dist/{build-cluster.d.ts → workers/compile-worker.d.ts} +0 -0
  183. /package/dist/{server-worker.d.ts → workers/lint-worker.d.ts} +0 -0
@@ -0,0 +1,250 @@
1
+ import { FsUtil, Logger, PathUtil, SdWorker, TNormPath } from "@simplysm/sd-core-node";
2
+ import path from "path";
3
+ import { EventEmitter } from "events";
4
+ import { SdServerBuildRunner } from "./server/SdServerBuildRunner";
5
+ import { SdClientBuildRunner } from "./client/SdClientBuildRunner";
6
+ import { SdTsLibBuildRunner } from "./lib/SdTsLibBuildRunner";
7
+ import { SdJsLibBuildRunner } from "./lib/SdJsLibBuildRunner";
8
+ import { ISdProjectConfig, ISdServerPackageConfig } from "../types/sd-configs.type";
9
+ import { ISdBuildMessage, ISdBuildRunnerResult } from "../types/build.type";
10
+ import { TServerWorkerType } from "../types/workers.type";
11
+ import { INpmConfig } from "../types/common-configs.type";
12
+
13
+ export class SdMultiBuildRunner extends EventEmitter {
14
+ #logger = Logger.get(["simplysm", "sd-cli", "SdMultiBuildRunner"]);
15
+
16
+ #busyCount = 0;
17
+
18
+ #resultCache = new Map<TNormPath, ISdBuildMessage[]>();
19
+ #serverInfoMap = new Map<
20
+ string,
21
+ {
22
+ pkgInfo?: { path: string; conf: ISdServerPackageConfig } | { port: number }; // persist
23
+ worker?: SdWorker<TServerWorkerType>; // persist
24
+ port?: number; // run server result
25
+ hasChanges: boolean;
26
+ clientChangedFileSet: Set<string>;
27
+
28
+ // from client
29
+ clients: Record<
30
+ string,
31
+ {
32
+ buildTypes: ("web" | "electron" | "cordova")[];
33
+ path: string;
34
+ }
35
+ >; // persist
36
+ }
37
+ >();
38
+
39
+ public override on(event: "change", listener: () => void): this;
40
+ public override on(event: "complete", listener: (result: ISdBuildMessage[]) => void): this;
41
+ public override on(event: string | symbol, listener: (...args: any[]) => void): this {
42
+ super.on(event, listener);
43
+ return this;
44
+ }
45
+
46
+ async runAsync(req: IRequest & { cmd: "watch" }): Promise<void>;
47
+ async runAsync(req: IRequest & { cmd: "build" }): Promise<ISdBuildMessage[]>;
48
+ async runAsync(req: IRequest): Promise<ISdBuildMessage[] | void> {
49
+ const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
50
+
51
+ const buildRunnerType =
52
+ pkgConf.type === "server"
53
+ ? SdServerBuildRunner
54
+ : pkgConf.type === "client"
55
+ ? SdClientBuildRunner
56
+ : FsUtil.exists(path.resolve(req.pkgPath, "tsconfig.json"))
57
+ ? SdTsLibBuildRunner
58
+ : SdJsLibBuildRunner;
59
+
60
+ const builder = new buildRunnerType(req.projConf, req.pkgPath)
61
+ .on("change", () => this.#onMessage(req, { type: "change" }))
62
+ .on("complete", (result) => this.#onMessage(req, { type: "complete", result }));
63
+
64
+ if (req.cmd === "build") {
65
+ const res = await builder.buildAsync();
66
+ return res.buildMessages;
67
+ } else {
68
+ await builder.watchAsync();
69
+ return;
70
+ }
71
+ }
72
+
73
+ #onMessage(req: IRequest, res: TResponse) {
74
+ if (res.type === "change") {
75
+ if (this.#busyCount === 0) {
76
+ this.emit("change");
77
+ }
78
+ this.#busyCount++;
79
+ } else {
80
+ this.#resultCache.delete(req.pkgPath);
81
+ for (const affectedFilePath of res.result.affectedFilePathSet) {
82
+ if (PathUtil.isChildPath(affectedFilePath, req.pkgPath)) {
83
+ this.#resultCache.delete(affectedFilePath);
84
+ }
85
+ }
86
+
87
+ for (const buildMessage of res.result.buildMessages) {
88
+ const cacheItem = this.#resultCache.getOrCreate(buildMessage.filePath ?? req.pkgPath, []);
89
+ cacheItem.push(buildMessage);
90
+ }
91
+
92
+ const pkgConf = req.projConf.packages[path.basename(req.pkgPath)]!;
93
+
94
+ if (pkgConf.type === "server") {
95
+ const pkgName = path.basename(req.pkgPath);
96
+ const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
97
+ hasChanges: true,
98
+ clientChangedFileSet: new Set(),
99
+ clients: {},
100
+ });
101
+
102
+ const serverPkgConf = req.projConf.packages[pkgName] as ISdServerPackageConfig;
103
+ serverInfo.pkgInfo = {
104
+ path: req.pkgPath,
105
+ conf: serverPkgConf,
106
+ };
107
+
108
+ serverInfo.hasChanges = true;
109
+ } else if (pkgConf.type === "client") {
110
+ const pkgName = path.basename(req.pkgPath);
111
+
112
+ if (pkgConf.server !== undefined) {
113
+ const serverInfo = this.#serverInfoMap.getOrCreate(
114
+ typeof pkgConf.server === "string" ? pkgConf.server : pkgConf.server.port.toString(),
115
+ {
116
+ hasChanges: true,
117
+ clientChangedFileSet: new Set(),
118
+ clients: {},
119
+ },
120
+ );
121
+
122
+ if (typeof pkgConf.server !== "string") {
123
+ serverInfo.pkgInfo = pkgConf.server;
124
+ }
125
+
126
+ serverInfo.clients[pkgName] = {
127
+ path: path.resolve(req.pkgPath, "dist"),
128
+ buildTypes: (pkgConf.builder ? Object.keys(pkgConf.builder) : ["web"]) as any,
129
+ };
130
+
131
+ serverInfo.clientChangedFileSet.adds(...res.result.emitFileSet);
132
+ } else {
133
+ const serverInfo = this.#serverInfoMap.getOrCreate(pkgName, {
134
+ hasChanges: true,
135
+ clientChangedFileSet: new Set(),
136
+ clients: {},
137
+ });
138
+
139
+ serverInfo.clientChangedFileSet.adds(...res.result.emitFileSet);
140
+ }
141
+ }
142
+
143
+ setTimeout(async () => {
144
+ this.#busyCount--;
145
+ if (this.#busyCount === 0) {
146
+ for (const serverPkgNameOrPort of this.#serverInfoMap.keys()) {
147
+ const serverInfo = this.#serverInfoMap.get(serverPkgNameOrPort)!;
148
+ if (serverInfo.pkgInfo && serverInfo.hasChanges) {
149
+ this.#logger.debug("서버 재시작...");
150
+ try {
151
+ const restartServerResult = await this.#restartServerAsync(serverInfo.pkgInfo, serverInfo.worker);
152
+ serverInfo.worker = restartServerResult.worker;
153
+ serverInfo.port = restartServerResult.port;
154
+ serverInfo.hasChanges = false;
155
+ } catch (err) {
156
+ this.#logger.error(err);
157
+ }
158
+ }
159
+
160
+ if (serverInfo.worker) {
161
+ this.#logger.debug("클라이언트 설정...");
162
+ await serverInfo.worker.run("setPathProxy", [
163
+ {
164
+ ...Object.keys(serverInfo.clients).toObject(
165
+ (key) => key,
166
+ (key) => serverInfo.clients[key].path,
167
+ ),
168
+ node_modules: path.resolve(process.cwd(), "node_modules"),
169
+ },
170
+ ]);
171
+
172
+ if (serverInfo.clientChangedFileSet.size > 0) {
173
+ this.#logger.debug("클라이언트 새로고침...");
174
+ await serverInfo.worker.run("broadcastReload", [serverInfo.clientChangedFileSet]);
175
+ }
176
+ }
177
+ }
178
+
179
+ const clientPaths: string[] = [];
180
+ for (const serverInfo of this.#serverInfoMap.values()) {
181
+ if (Object.keys(serverInfo.clients).length > 0) {
182
+ for (const clientPkgName of Object.keys(serverInfo.clients)) {
183
+ for (const buildType of serverInfo.clients[clientPkgName].buildTypes) {
184
+ if (buildType === "web") {
185
+ clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/`);
186
+ } else {
187
+ clientPaths.push(`http://localhost:${serverInfo.port}/${clientPkgName}/${buildType}/`);
188
+ }
189
+ }
190
+ }
191
+ } else {
192
+ clientPaths.push(`http://localhost:${serverInfo.port}/`);
193
+ }
194
+ }
195
+ if (clientPaths.length > 0) {
196
+ this.#logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
197
+ }
198
+
199
+ const messages = Array.from(this.#resultCache.values()).mapMany();
200
+ this.emit("complete", messages);
201
+ }
202
+ }, 300);
203
+ }
204
+ }
205
+
206
+ async #restartServerAsync(
207
+ pkgInfo: { path: string; conf: ISdServerPackageConfig } | { port: number },
208
+ prevWorker?: SdWorker<TServerWorkerType>,
209
+ ): Promise<{
210
+ worker: SdWorker<TServerWorkerType>;
211
+ port: number;
212
+ }> {
213
+ const logger = Logger.get(["simplysm", "sd-cli", "SdMultiBuildRunner", "#restartServerAsync"]);
214
+
215
+ if (prevWorker) {
216
+ prevWorker.kill();
217
+ }
218
+
219
+ const npmConf =
220
+ "path" in pkgInfo ? (FsUtil.readJson(path.resolve(pkgInfo.path, "package.json")) as INpmConfig) : undefined;
221
+
222
+ const worker = new SdWorker<TServerWorkerType>(import.meta.resolve("../workers/server-worker"), {
223
+ env: {
224
+ NODE_ENV: "development",
225
+ TZ: "Asia/Seoul",
226
+ SD_VERSION: npmConf?.version ?? "serverless",
227
+ ...("path" in pkgInfo ? pkgInfo.conf.env : {}),
228
+ },
229
+ });
230
+ const port = await worker.run("listen", [pkgInfo]);
231
+ logger.debug("서버가 시작되었습니다.");
232
+
233
+ return { worker, port };
234
+ }
235
+ }
236
+
237
+ interface IRequest {
238
+ cmd: "watch" | "build";
239
+ pkgPath: TNormPath;
240
+ projConf: ISdProjectConfig;
241
+ }
242
+
243
+ type TResponse =
244
+ | {
245
+ type: "change";
246
+ }
247
+ | {
248
+ type: "complete";
249
+ result: ISdBuildRunnerResult;
250
+ };
@@ -3,24 +3,24 @@ import { FsUtil, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
3
3
  import { StringUtil } from "@simplysm/sd-core-common";
4
4
 
5
5
  export class SdCliNgRoutesFileGenerator {
6
- public static async watchAsync(pkgPath: string, noLazyRoute?: boolean): Promise<void> {
6
+ static watch(pkgPath: string, noLazyRoute?: boolean) {
7
7
  const routesFilePath = path.resolve(pkgPath, "src/routes.ts");
8
8
  let cache = FsUtil.exists(routesFilePath) ? FsUtil.readFile(routesFilePath) : undefined;
9
9
 
10
- SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({}, async () => {
11
- cache = await this.runAsync(pkgPath, cache, noLazyRoute);
10
+ SdFsWatcher.watch([path.resolve(pkgPath, "src")]).onChange({ delay: 100 }, () => {
11
+ cache = this.run(pkgPath, cache, noLazyRoute);
12
12
  });
13
13
 
14
- cache = await this.runAsync(pkgPath, cache, noLazyRoute);
14
+ cache = this.run(pkgPath, cache, noLazyRoute);
15
15
  }
16
16
 
17
- public static async runAsync(pkgPath: string, cache?: string, noLazyRoute?: boolean): Promise<string> {
17
+ static run(pkgPath: string, cache?: string, noLazyRoute?: boolean): string {
18
18
  const appDirPath = path.resolve(pkgPath, "src/app");
19
19
  const routesFilePath = path.resolve(pkgPath, "src/routes.ts");
20
20
 
21
21
  // 내부 파일들 import
22
22
  const result: TInfo = new Map();
23
- const filePaths = await FsUtil.globAsync(path.resolve(appDirPath, "**/*Page.ts"));
23
+ const filePaths = FsUtil.glob(path.resolve(appDirPath, "**/*Page.ts"));
24
24
  for (const filePath of filePaths.orderBy()) {
25
25
  const relModulePath = PathUtil.posix(path.relative(appDirPath, filePath)).slice(0, -3);
26
26
  const codes = relModulePath
@@ -76,7 +76,7 @@ export const routes: Routes = [
76
76
  ${routes}
77
77
  ];`.trim();
78
78
  if (content !== cache) {
79
- await FsUtil.writeFileAsync(routesFilePath, content);
79
+ FsUtil.writeFile(routesFilePath, content);
80
80
  }
81
81
  return content;
82
82
  }
@@ -0,0 +1,191 @@
1
+ import { EventEmitter } from "events";
2
+ import { FsUtil, Logger, PathUtil, SdFsWatcher, TNormPath } from "@simplysm/sd-core-node";
3
+ import path from "path";
4
+ import { SdNgBundler } from "./SdNgBundler";
5
+ import { SdCliNgRoutesFileGenerator } from "./SdCliNgRoutesFileGenerator";
6
+ import { SdCliCordova } from "../../entry/SdCliCordova";
7
+ import { SdCliElectron } from "../../entry/SdCliElectron";
8
+ import { ISdClientPackageConfig, ISdProjectConfig } from "../../types/sd-configs.type";
9
+ import { INpmConfig } from "../../types/common-configs.type";
10
+ import { ISdBuildMessage, ISdBuildRunnerResult } from "../../types/build.type";
11
+
12
+ export class SdClientBuildRunner extends EventEmitter {
13
+ private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdClientBuildRunner"]);
14
+ private readonly _pkgConf: ISdClientPackageConfig;
15
+ private readonly _npmConf: INpmConfig;
16
+ private _ngBundlers?: SdNgBundler[];
17
+ private _cordova?: SdCliCordova;
18
+
19
+ public constructor(
20
+ private readonly _projConf: ISdProjectConfig,
21
+ private readonly _pkgPath: TNormPath,
22
+ ) {
23
+ super();
24
+ this._pkgConf = this._projConf.packages[path.basename(_pkgPath)] as ISdClientPackageConfig;
25
+ this._npmConf = FsUtil.readJson(path.resolve(_pkgPath, "package.json")) as INpmConfig;
26
+ }
27
+
28
+ public override on(event: "change", listener: () => void): this;
29
+ public override on(event: "complete", listener: (result: ISdBuildRunnerResult) => void): this;
30
+ public override on(event: string | symbol, listener: (...args: any[]) => void): this {
31
+ super.on(event, listener);
32
+ return this;
33
+ }
34
+
35
+ public async buildAsync(): Promise<ISdBuildRunnerResult> {
36
+ this._debug("dist 초기화...");
37
+ FsUtil.remove(path.resolve(this._pkgPath, "dist"));
38
+
39
+ if (this._npmConf.dependencies && Object.keys(this._npmConf.dependencies).includes("@angular/router")) {
40
+ this._debug(`GEN routes.ts...`);
41
+ SdCliNgRoutesFileGenerator.run(this._pkgPath, undefined, this._pkgConf.noLazyRoute);
42
+ }
43
+
44
+ this._debug("GEN .config...");
45
+ const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
46
+ FsUtil.writeFile(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
47
+
48
+ const result = await this._runAsync({ dev: false });
49
+ return {
50
+ affectedFilePathSet: result.affectedFileSet,
51
+ buildMessages: result.buildMessages,
52
+ emitFileSet: result.emitFileSet,
53
+ };
54
+ }
55
+
56
+ public async watchAsync() {
57
+ this.emit("change");
58
+
59
+ this._debug("dist 초기화...");
60
+ FsUtil.remove(path.resolve(this._pkgPath, "dist"));
61
+
62
+ if (this._npmConf.dependencies && Object.keys(this._npmConf.dependencies).includes("@angular/router")) {
63
+ this._debug(`WATCH GEN routes.ts...`);
64
+ SdCliNgRoutesFileGenerator.watch(this._pkgPath, this._pkgConf.noLazyRoute);
65
+ }
66
+
67
+ this._debug("GEN .config...");
68
+ const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
69
+ FsUtil.writeFile(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
70
+
71
+ const result = await this._runAsync({ dev: !this._pkgConf.forceProductionMode });
72
+ const res: ISdBuildRunnerResult = {
73
+ affectedFilePathSet: result.affectedFileSet,
74
+ buildMessages: result.buildMessages,
75
+ emitFileSet: result.emitFileSet,
76
+ };
77
+ this.emit("complete", res);
78
+
79
+ this._debug("WATCH...");
80
+ const watcher = SdFsWatcher.watch(Array.from(result.watchFileSet)).onChange({ delay: 300 }, async (changeInfos) => {
81
+ this.emit("change");
82
+
83
+ for (const ngBundler of this._ngBundlers!) {
84
+ ngBundler.markForChanges(changeInfos.map((item) => item.path));
85
+ }
86
+
87
+ const watchResult = await this._runAsync({ dev: !this._pkgConf.forceProductionMode });
88
+ const watchRes: ISdBuildRunnerResult = {
89
+ affectedFilePathSet: watchResult.affectedFileSet,
90
+ buildMessages: watchResult.buildMessages,
91
+ emitFileSet: watchResult.emitFileSet,
92
+ };
93
+ this.emit("complete", watchRes);
94
+
95
+ watcher.replaceWatchPaths(watchResult.watchFileSet);
96
+ });
97
+ }
98
+
99
+ private async _runAsync(opt: { dev: boolean }): Promise<{
100
+ watchFileSet: Set<TNormPath>;
101
+ affectedFileSet: Set<TNormPath>;
102
+ buildMessages: ISdBuildMessage[];
103
+ emitFileSet: Set<TNormPath>;
104
+ }> {
105
+ const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {}).mapMany((key) =>
106
+ FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)),
107
+ );
108
+
109
+ const ngBundlerBuilderTypes = Object.keys(this._pkgConf.builder ?? { web: {} }) as (
110
+ | "web"
111
+ | "electron"
112
+ | "cordova"
113
+ )[];
114
+ if (this._pkgConf.builder?.cordova && !this._cordova) {
115
+ this._debug("CORDOVA 준비...");
116
+ this._cordova = new SdCliCordova({
117
+ pkgPath: this._pkgPath,
118
+ config: this._pkgConf.builder.cordova,
119
+ });
120
+ await this._cordova.initializeAsync();
121
+ }
122
+
123
+ if (!this._ngBundlers) {
124
+ this._debug(`BUILD 준비...`);
125
+
126
+ this._ngBundlers = ngBundlerBuilderTypes.map(
127
+ (ngBundlerBuilderType) =>
128
+ new SdNgBundler({
129
+ dev: opt.dev,
130
+ builderType: ngBundlerBuilderType,
131
+ pkgPath: this._pkgPath,
132
+ outputPath:
133
+ ngBundlerBuilderType === "web"
134
+ ? PathUtil.norm(this._pkgPath, "dist")
135
+ : ngBundlerBuilderType === "electron" && !opt.dev
136
+ ? PathUtil.norm(this._pkgPath, ".electron/src")
137
+ : ngBundlerBuilderType === "cordova" && !opt.dev
138
+ ? PathUtil.norm(this._pkgPath, ".cordova/www")
139
+ : PathUtil.norm(this._pkgPath, "dist", ngBundlerBuilderType),
140
+ env: {
141
+ ...this._pkgConf.env,
142
+ ...this._pkgConf.builder?.[ngBundlerBuilderType]?.env,
143
+ },
144
+ cordovaConfig: ngBundlerBuilderType === "cordova" ? this._pkgConf.builder!.cordova : undefined,
145
+ watchScopePaths: [path.resolve(this._pkgPath, "../"), ...localUpdatePaths].map((item) =>
146
+ PathUtil.norm(item),
147
+ ),
148
+ }),
149
+ );
150
+ }
151
+
152
+ this._debug(`BUILD...`);
153
+ const buildResults = await Promise.all(this._ngBundlers.map((builder) => builder.bundleAsync()));
154
+ const watchFileSet = new Set(buildResults.mapMany((item) => Array.from(item.watchFileSet)));
155
+ const affectedFileSet = new Set(buildResults.mapMany((item) => Array.from(item.affectedFileSet)));
156
+ const emitFileSet = new Set(buildResults.mapMany((item) => Array.from(item.emitFileSet)));
157
+ const results = buildResults.mapMany((item) => item.results).distinct();
158
+
159
+ if (!opt.dev && this._cordova) {
160
+ this._debug("CORDOVA BUILD...");
161
+ await this._cordova.buildAsync(path.resolve(this._pkgPath, "dist"));
162
+ }
163
+
164
+ if (!opt.dev && this._pkgConf.builder?.electron) {
165
+ this._debug("ELECTRON BUILD...");
166
+ await SdCliElectron.buildAsync({
167
+ pkgPath: this._pkgPath,
168
+ config: this._pkgConf.builder.electron,
169
+ });
170
+ }
171
+
172
+ this._debug(`빌드 완료`);
173
+ const currWatchFileSet = new Set(
174
+ Array.from(watchFileSet).filter(
175
+ (item) =>
176
+ PathUtil.isChildPath(item, path.resolve(this._pkgPath, "../")) ||
177
+ localUpdatePaths.some((lu) => PathUtil.isChildPath(item, lu)),
178
+ ),
179
+ );
180
+ return {
181
+ watchFileSet: currWatchFileSet,
182
+ affectedFileSet,
183
+ buildMessages: results, //.filter((item) => item.filePath !== path.resolve(this._pkgPath, "src/routes.ts")),
184
+ emitFileSet,
185
+ };
186
+ }
187
+
188
+ private _debug(msg: string): void {
189
+ this._logger.debug(`[${path.basename(this._pkgPath)}] ${msg}`);
190
+ }
191
+ }