@simplysm/sd-cli 10.0.36 → 10.0.39

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/SdLinter.js.map +1 -1
  2. package/dist/SdTsIncrementalBuilder.d.ts +17 -4
  3. package/dist/SdTsIncrementalBuilder.js +29 -33
  4. package/dist/SdTsIncrementalBuilder.js.map +1 -1
  5. package/dist/build-cluster.js +98 -30
  6. package/dist/build-cluster.js.map +1 -1
  7. package/dist/builders/SdCliClientBuilder.d.ts +6 -2
  8. package/dist/builders/SdCliClientBuilder.js +107 -97
  9. package/dist/builders/SdCliClientBuilder.js.map +1 -1
  10. package/dist/builders/SdCliJsLibLinter.js.map +1 -1
  11. package/dist/builders/SdCliServerBuilder.d.ts +2 -1
  12. package/dist/builders/SdCliServerBuilder.js +68 -13
  13. package/dist/builders/SdCliServerBuilder.js.map +1 -1
  14. package/dist/builders/SdCliTsLibBuilder.d.ts +5 -2
  15. package/dist/builders/SdCliTsLibBuilder.js +64 -10
  16. package/dist/builders/SdCliTsLibBuilder.js.map +1 -1
  17. package/dist/commons.d.ts +28 -2
  18. package/dist/commons.js.map +1 -1
  19. package/dist/entry/SdCliElectron.d.ts +7 -0
  20. package/dist/entry/SdCliElectron.js +42 -0
  21. package/dist/entry/SdCliElectron.js.map +1 -0
  22. package/dist/entry/SdCliLocalUpdate.d.ts +3 -3
  23. package/dist/entry/SdCliLocalUpdate.js +20 -26
  24. package/dist/entry/SdCliLocalUpdate.js.map +1 -1
  25. package/dist/entry/SdCliProject.d.ts +3 -3
  26. package/dist/entry/SdCliProject.js +87 -36
  27. package/dist/entry/SdCliProject.js.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/sd-cli.d.ts +1 -1
  32. package/dist/sd-cli.js +62 -16
  33. package/dist/sd-cli.js.map +1 -1
  34. package/dist/server-worker.js.map +1 -1
  35. package/dist/utils/SdCliBuildResultUtil.js +1 -1
  36. package/dist/utils/SdCliBuildResultUtil.js.map +1 -1
  37. package/dist/utils/SdCliViteElectronMainPlugin.d.ts +6 -0
  38. package/dist/utils/SdCliViteElectronMainPlugin.js +81 -0
  39. package/dist/utils/SdCliViteElectronMainPlugin.js.map +1 -0
  40. package/dist/utils/SdCliViteExternalPlugin.d.ts +7 -0
  41. package/dist/utils/SdCliViteExternalPlugin.js +98 -0
  42. package/dist/utils/SdCliViteExternalPlugin.js.map +1 -0
  43. package/dist/utils/SdCliViteLoggerPlugin.d.ts +6 -0
  44. package/dist/utils/SdCliViteLoggerPlugin.js +24 -0
  45. package/dist/utils/SdCliViteLoggerPlugin.js.map +1 -0
  46. package/dist/utils/SdCliViteNodeGlobalPlugin.d.ts +2 -0
  47. package/dist/utils/SdCliViteNodeGlobalPlugin.js +29 -0
  48. package/dist/utils/SdCliViteNodeGlobalPlugin.js.map +1 -0
  49. package/dist/utils/SdCliViteReactSwcPlugin.d.ts +2 -0
  50. package/dist/utils/SdCliViteReactSwcPlugin.js +141 -0
  51. package/dist/utils/SdCliViteReactSwcPlugin.js.map +1 -0
  52. package/dist/utils/SdCliViteWatchWithResolutionsPlugin.d.ts +2 -0
  53. package/dist/utils/SdCliViteWatchWithResolutionsPlugin.js +26 -0
  54. package/dist/utils/SdCliViteWatchWithResolutionsPlugin.js.map +1 -0
  55. package/dist/utils/getElectronReactExternals.d.ts +1 -0
  56. package/dist/utils/getElectronReactExternals.js +17 -0
  57. package/dist/utils/getElectronReactExternals.js.map +1 -0
  58. package/dist/utils/sdCliTsDefineTransformer.d.ts +4 -0
  59. package/dist/utils/sdCliTsDefineTransformer.js +26 -0
  60. package/dist/utils/sdCliTsDefineTransformer.js.map +1 -0
  61. package/package.json +25 -10
  62. package/src/SdLinter.ts +2 -2
  63. package/src/SdTsIncrementalBuilder.ts +116 -94
  64. package/src/build-cluster.ts +173 -111
  65. package/src/builders/SdCliClientBuilder.ts +226 -204
  66. package/src/builders/SdCliServerBuilder.ts +311 -240
  67. package/src/builders/SdCliTsLibBuilder.ts +160 -89
  68. package/src/commons.ts +66 -34
  69. package/src/entry/SdCliElectron.ts +55 -0
  70. package/src/entry/SdCliLocalUpdate.ts +104 -101
  71. package/src/entry/SdCliProject.ts +452 -401
  72. package/src/index.ts +1 -0
  73. package/src/sd-cli.ts +185 -141
  74. package/src/utils/SdCliBuildResultUtil.ts +1 -2
  75. package/src/utils/SdCliViteElectronMainPlugin.ts +86 -0
  76. package/src/utils/SdCliViteExternalPlugin.ts +112 -0
  77. package/src/utils/SdCliViteLoggerPlugin.ts +29 -0
  78. package/src/utils/SdCliViteNodeGlobalPlugin.ts +31 -0
  79. package/src/utils/SdCliViteReactSwcPlugin.ts +154 -0
  80. package/src/utils/SdCliViteWatchWithResolutionsPlugin.ts +29 -0
  81. package/src/utils/getElectronReactExternals.ts +19 -0
  82. package/src/utils/sdCliTsDefineTransformer.ts +31 -0
  83. package/.eslintrc.cjs +0 -18
  84. package/dist/utils/SdCliConfigUtil.d.ts +0 -7
  85. package/dist/utils/SdCliConfigUtil.js +0 -69
  86. package/dist/utils/SdCliConfigUtil.js.map +0 -1
  87. package/src/utils/SdCliConfigUtil.ts +0 -94
@@ -1,473 +1,524 @@
1
1
  import path from "path";
2
- import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
3
- import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
2
+ import {FsUtil, Logger, SdProcess} from "@simplysm/sd-core-node";
4
3
  import {
5
- INpmConfig,
6
- ISdCliBuildClusterReqMessage,
7
- ISdCliBuildClusterResMessage,
8
- ISdCliPackageBuildResult,
9
- TSdCliPackageConfig
4
+ INpmConfig,
5
+ ISdCliBuildClusterReqMessage,
6
+ ISdCliBuildClusterResMessage,
7
+ ISdCliConfig,
8
+ ISdCliPackageBuildResult,
9
+ TSdCliPackageConfig
10
10
  } from "../commons";
11
11
  import cp from "child_process";
12
- import { fileURLToPath } from "url";
13
- import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
12
+ import {fileURLToPath, pathToFileURL} from "url";
13
+ import {SdCliBuildResultUtil} from "../utils/SdCliBuildResultUtil";
14
14
  import semver from "semver";
15
- import { NotImplementError, Wait } from "@simplysm/sd-core-common";
16
- import { SdCliLocalUpdate } from "./SdCliLocalUpdate";
15
+ import {NotImplementError, Wait} from "@simplysm/sd-core-common";
17
16
 
18
17
  export class SdCliProject {
19
- public static async watchAsync(opt: {
20
- rootPath: string;
21
- confFileRelPath: string;
22
- optNames: string[];
23
- pkgNames: string[];
24
- }): Promise<void> {
25
- const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "watchAsync"]);
26
-
27
- logger.debug("프로젝트 설정 가져오기...");
28
- const projConf = await SdCliConfigUtil.loadConfigAsync(path.resolve(opt.rootPath, opt.confFileRelPath), false, opt.optNames);
29
-
30
- if (projConf.localUpdates) {
31
- logger.debug("로컬 라이브러리 업데이트 변경감지 시작...");
32
- await SdCliLocalUpdate.watchAsync({ rootPath: opt.rootPath, confFileRelPath: opt.confFileRelPath });
33
- }
34
-
35
- logger.debug("프로젝트 package.json 가져오기...");
36
- const projNpmConf = FsUtil.readJson(path.resolve(opt.rootPath, "package.json"));
37
-
38
- logger.debug("패키지 목록 구성...");
39
- const allPkgPaths = await projNpmConf.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
40
- let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
41
- if (opt.pkgNames.length !== 0) {
42
- pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
43
- }
44
-
45
- logger.debug("빌드 프로세스 준비...");
46
- const cluster = await this._prepareClusterAsync();
47
-
48
- logger.debug("빌드 프로세스 이벤트 준비...");
49
- const resultCache = new Map<string, ISdCliPackageBuildResult[]>();
50
- let busyCount = 0;
51
- const serverInfoMap = new Map<string, {
52
- // server
53
- pkgPath?: string; // persist
54
- worker?: cp.ChildProcess; // persist
55
- port?: number;
56
- hasChanges: boolean;
57
-
58
- //client
59
- pathProxy: Record<string, number | undefined>; // persist
60
- changeFilePaths: string[];
61
- }>();
62
- cluster.on("message", (message: ISdCliBuildClusterResMessage) => {
63
- if (message.type === "change") {
64
- if (busyCount === 0) {
65
- logger.log("빌드를 시작합니다...");
18
+ public static async watchAsync(opt: {
19
+ confFileRelPath: string;
20
+ optNames: string[];
21
+ pkgNames: string[];
22
+ withLint: boolean;
23
+ }): Promise<void> {
24
+ const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "watchAsync"]);
25
+
26
+ logger.debug("프로젝트 설정 가져오기...");
27
+ const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(true, opt.optNames) as ISdCliConfig;
28
+
29
+ logger.debug("프로젝트 package.json 가져오기...");
30
+ const projNpmConf = (await FsUtil.readJsonAsync(path.resolve(process.cwd(), "package.json"))) as INpmConfig;
31
+
32
+ logger.debug("패키지 목록 구성...");
33
+ if (!projNpmConf.workspaces) {
34
+ throw new Error("프로젝트 package.json workspaces가 설정되어있지 않습니다.");
66
35
  }
67
- busyCount++;
68
- }
69
- else if (message.type === "complete") {
70
- for (const affectedFilePath of message.result!.affectedFilePaths) {
71
- resultCache.delete(affectedFilePath);
36
+ const allPkgPaths = await projNpmConf.workspaces.mapManyAsync(async (item) => await FsUtil.globAsync(item));
37
+ let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
38
+ if (opt.pkgNames.length !== 0) {
39
+ pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
72
40
  }
73
41
 
74
- for (const buildResult of message.result!.buildResults) {
75
- const cacheItem = resultCache.getOrCreate(buildResult.filePath ?? "none", []);
76
- cacheItem.push(buildResult);
42
+ logger.debug("패키지 존재 확인...");
43
+ const notExistsPkgs = Object.keys(projConf.packages).filter((pkgConfKey) => allPkgPaths.every((pkgPath) => path.basename(pkgPath) !== pkgConfKey));
44
+ if (notExistsPkgs.length > 0) {
45
+ throw new Error("패키지를 찾을 수 없습니다. (" + notExistsPkgs.join(", ") + ")");
77
46
  }
78
47
 
79
- if (message.req.pkgConf.type === "server") {
80
- const pkgName = path.basename(message.req.pkgPath);
81
- const serverInfo = serverInfoMap.getOrCreate(pkgName, {
82
- hasChanges: false,
83
- pathProxy: {},
84
- changeFilePaths: []
85
- });
86
- serverInfo.pkgPath = message.req.pkgPath;
87
- serverInfo.hasChanges = true;
88
- }
48
+ logger.debug("빌드 프로세스 준비...");
49
+ const cluster = await this._prepareClusterAsync();
50
+
51
+ logger.debug("빌드 프로세스 이벤트 준비...");
52
+ const resultCache = new Map<string, ISdCliPackageBuildResult[]>();
53
+ let busyCount = 0;
54
+ const serverInfoMap = new Map<string, {
55
+ // server
56
+ pkgPath?: string; // persist
57
+ worker?: cp.ChildProcess; // persist
58
+ port?: number;
59
+ hasChanges: boolean;
60
+
61
+ //client
62
+ pathProxy: Record<string, number | undefined>; // persist
63
+ changeFilePaths: string[];
64
+ }>();
65
+ cluster.on("message", (message: ISdCliBuildClusterResMessage) => {
66
+ if (message.type === "change") {
67
+ if (busyCount === 0) {
68
+ logger.log("빌드를 시작합니다...");
69
+ }
70
+ busyCount++;
71
+ } else if (message.type === "complete") {
72
+ for (const affectedFilePath of message.result!.affectedFilePaths) {
73
+ resultCache.delete(affectedFilePath);
74
+ }
89
75
 
90
- if (message.req.pkgConf.type === "client" && message.req.pkgConf.server !== undefined) {
91
- const pkgName = path.basename(message.req.pkgPath);
92
- const serverInfo = serverInfoMap.getOrCreate(message.req.pkgConf.server, {
93
- hasChanges: false,
94
- pathProxy: {},
95
- changeFilePaths: []
96
- });
97
- serverInfo.pathProxy[pkgName] = message.result!.port;
98
- serverInfo.changeFilePaths.push(...message.result!.affectedFilePaths);
99
- }
76
+ for (const buildResult of message.result!.buildResults) {
77
+ const cacheItem = resultCache.getOrCreate(buildResult.filePath ?? "none", []);
78
+ cacheItem.push(buildResult);
79
+ }
100
80
 
101
- setTimeout(async () => {
102
- busyCount--;
103
- if (busyCount === 0) {
104
- for (const serverPkgName of serverInfoMap.keys()) {
105
- const serverInfo = serverInfoMap.get(serverPkgName)!;
106
- if (serverInfo.pkgPath !== undefined && serverInfo.hasChanges) {
107
- logger.debug("서버 재시작...");
108
- try {
109
- const restartServerResult = await this._restartServerAsync(serverInfo.pkgPath, serverInfo.worker);
110
- serverInfo.worker = restartServerResult.worker;
111
- serverInfo.port = restartServerResult.port;
112
- serverInfo.hasChanges = false;
81
+ if (message.req.pkgConf.type === "server") {
82
+ const pkgName = path.basename(message.req.pkgPath);
83
+ const serverInfo = serverInfoMap.getOrCreate(pkgName, {
84
+ hasChanges: false,
85
+ pathProxy: {},
86
+ changeFilePaths: []
87
+ });
88
+ serverInfo.pkgPath = message.req.pkgPath;
89
+ serverInfo.hasChanges = true;
113
90
  }
114
- catch (err) {
115
- logger.error(err);
91
+
92
+ if (message.req.pkgConf.type === "client") {
93
+ const pkgName = path.basename(message.req.pkgPath);
94
+
95
+ if (message.req.pkgConf.server !== undefined) {
96
+ const serverInfo = serverInfoMap.getOrCreate(message.req.pkgConf.server, {
97
+ hasChanges: false,
98
+ pathProxy: {},
99
+ changeFilePaths: []
100
+ });
101
+ serverInfo.pathProxy[pkgName] = message.result!.port;
102
+ serverInfo.changeFilePaths.push(...message.result!.affectedFilePaths);
103
+ } else {
104
+ const serverInfo = serverInfoMap.getOrCreate(pkgName, {
105
+ hasChanges: false,
106
+ pathProxy: {},
107
+ changeFilePaths: []
108
+ });
109
+ serverInfo.port = message.result!.port;
110
+ serverInfo.changeFilePaths.push(...message.result!.affectedFilePaths);
111
+ }
116
112
  }
117
- }
118
113
 
119
- if (serverInfo.worker) {
120
- logger.debug("클라이언트 설정...");
121
- serverInfo.worker.send({
122
- type: "setPathProxy",
123
- pathProxy: serverInfo.pathProxy
124
- });
125
- }
114
+ setTimeout(async () => {
115
+ busyCount--;
116
+ if (busyCount === 0) {
117
+ for (const serverPkgName of serverInfoMap.keys()) {
118
+ const serverInfo = serverInfoMap.get(serverPkgName)!;
119
+ if (serverInfo.pkgPath !== undefined && serverInfo.hasChanges) {
120
+ logger.debug("서버 재시작...");
121
+ try {
122
+ const restartServerResult = await this._restartServerAsync(serverInfo.pkgPath, serverInfo.worker);
123
+ serverInfo.worker = restartServerResult.worker;
124
+ serverInfo.port = restartServerResult.port;
125
+ serverInfo.hasChanges = false;
126
+ } catch (err) {
127
+ logger.error(err);
128
+ }
129
+ }
130
+
131
+ if (serverInfo.worker) {
132
+ logger.debug("클라이언트 설정...");
133
+ serverInfo.worker.send({
134
+ type: "setPathProxy",
135
+ pathProxy: serverInfo.pathProxy
136
+ });
137
+ }
138
+ }
139
+
140
+ const clientPaths: string[] = [];
141
+ for (const serverInfo of serverInfoMap.values()) {
142
+ if (Object.keys(serverInfo.pathProxy).length > 0) {
143
+ for (const proxyPath of Object.keys(serverInfo.pathProxy)) {
144
+ clientPaths.push(`http://localhost:${serverInfo.port}/${proxyPath}/`);
145
+ }
146
+ } else {
147
+ clientPaths.push(`http://localhost:${serverInfo.port}/`);
148
+ }
149
+ }
150
+ if (clientPaths.length > 0) {
151
+ logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
152
+ }
153
+
154
+ const buildResults = Array.from(resultCache.values()).mapMany();
155
+ this._logging(buildResults, logger);
156
+ }
157
+ }, 300);
126
158
  }
159
+ });
127
160
 
128
- const clientPaths: string[] = [];
129
- for (const serverInfo of serverInfoMap.values()) {
130
- for (const proxyPath of Object.keys(serverInfo.pathProxy)) {
131
- clientPaths.push(`http://localhost:${serverInfo.port}/${proxyPath}/`);
132
- }
133
- }
134
- if (clientPaths.length > 0) {
135
- logger.info("클라이언트 개발 서버 접속 주소\n" + clientPaths.join("\n"));
161
+ logger.debug("빌드 프로세스 명령 전송...");
162
+ busyCount++;
163
+ logger.log("빌드를 시작합니다...");
164
+
165
+ await pkgPaths.parallelAsync(async (pkgPath) => {
166
+ const pkgConf = projConf.packages[path.basename(pkgPath)]!;
167
+ if (pkgConf.type === "client") {
168
+ const builderKeys = Object.keys(pkgConf.builder ?? {web: {}});
169
+ await builderKeys.parallelAsync(async (builderKey) => {
170
+ await this._runCommandAsync(cluster, "watch", pkgPath, projConf.packages[path.basename(pkgPath)]!, opt.withLint, builderKey);
171
+ });
172
+ } else {
173
+ await this._runCommandAsync(cluster, "watch", pkgPath, projConf.packages[path.basename(pkgPath)]!, opt.withLint);
136
174
  }
175
+ });
137
176
 
177
+ busyCount--;
178
+ if (busyCount === 0) {
138
179
  const buildResults = Array.from(resultCache.values()).mapMany();
139
180
  this._logging(buildResults, logger);
140
- }
141
- }, 300);
142
- }
143
- });
144
-
145
- logger.debug("빌드 프로세스 명령 전송...");
146
- busyCount++;
147
- logger.log("빌드를 시작합니다...");
148
-
149
- await pkgPaths.parallelAsync(async (pkgPath) => {
150
- await this._runCommandAsync(cluster, "watch", pkgPath, projConf.packages[path.basename(pkgPath)]!);
151
- });
152
-
153
- busyCount--;
154
- if (busyCount === 0) {
155
- const buildResults = Array.from(resultCache.values()).mapMany();
156
- this._logging(buildResults, logger);
157
- }
158
- }
159
-
160
- public static async buildAsync(opt: {
161
- rootPath: string;
162
- confFileRelPath: string;
163
- optNames: string[];
164
- pkgNames: string[];
165
- }): Promise<void> {
166
- const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "buildAsync"]);
167
-
168
- logger.debug("프로젝트 설정 가져오기...");
169
- const projConf = await SdCliConfigUtil.loadConfigAsync(path.resolve(opt.rootPath, opt.confFileRelPath), false, opt.optNames);
170
-
171
- logger.debug("프로젝트 package.json 가져오기...");
172
- const projNpmConf = FsUtil.readJson(path.resolve(opt.rootPath, "package.json"));
173
-
174
- logger.debug("패키지 목록 구성...");
175
- const allPkgPaths = await projNpmConf.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
176
- let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
177
- if (opt.pkgNames.length !== 0) {
178
- pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
181
+ }
179
182
  }
180
183
 
181
- logger.debug("프로젝트 패키지 버전 설정...");
182
- await this._upgradeVersionAsync(opt.rootPath, projNpmConf, allPkgPaths);
184
+ public static async buildAsync(opt: {
185
+ confFileRelPath: string;
186
+ optNames: string[];
187
+ pkgNames: string[];
188
+ withLint: boolean;
189
+ }): Promise<void> {
190
+ const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "buildAsync"]);
183
191
 
184
- logger.debug("빌드 프로세스 준비...");
185
- const cluster = await this._prepareClusterAsync();
192
+ logger.debug("프로젝트 설정 가져오기...");
193
+ const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(false, opt.optNames) as ISdCliConfig;
186
194
 
187
- logger.debug("빌드 프로세스 명령 전달...");
188
- const results = (
189
- await pkgPaths.parallelAsync(async (pkgPath) => {
190
- return await this._runCommandAsync(cluster, "build", pkgPath, projConf.packages[path.basename(pkgPath)]!);
191
- })
192
- ).mapMany();
195
+ logger.debug("프로젝트 package.json 가져오기...");
196
+ const projNpmConf = (await FsUtil.readJsonAsync(path.resolve(process.cwd(), "package.json"))) as INpmConfig;
193
197
 
194
- logger.debug("빌드 프로세스 닫기...");
195
- this._closeCluster(cluster);
198
+ logger.debug("패키지 목록 구성...");
199
+ if (!projNpmConf.workspaces) {
200
+ throw new Error("프로젝트 package.json에 workspaces가 설정되어있지 않습니다.");
201
+ }
202
+ const allPkgPaths = await projNpmConf.workspaces.mapManyAsync(async (item) => await FsUtil.globAsync(item));
203
+ let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
204
+ if (opt.pkgNames.length !== 0) {
205
+ pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
206
+ }
196
207
 
197
- this._logging(results, logger);
198
- }
208
+ logger.debug("프로젝트 및 패키지 버전 설정...");
209
+ await this._upgradeVersionAsync(projNpmConf, allPkgPaths);
210
+
211
+ logger.debug("빌드 프로세스 준비...");
212
+ const cluster = await this._prepareClusterAsync();
213
+
214
+ logger.debug("빌드 프로세스 명령 전달...");
215
+ const results = (
216
+ await pkgPaths.parallelAsync(async (pkgPath) => {
217
+ const pkgConf = projConf.packages[path.basename(pkgPath)]!;
218
+ if (pkgConf.type === "client") {
219
+ const builderKeys = Object.keys(pkgConf.builder ?? {web: {}});
220
+ return (await builderKeys.parallelAsync(async (builderKey) => {
221
+ return await this._runCommandAsync(cluster, "build", pkgPath, projConf.packages[path.basename(pkgPath)]!, opt.withLint, builderKey);
222
+ })).mapMany();
223
+ } else {
224
+ return await this._runCommandAsync(cluster, "build", pkgPath, projConf.packages[path.basename(pkgPath)]!, opt.withLint);
225
+ }
226
+ })
227
+ ).mapMany();
199
228
 
200
- public static async publishAsync(opt: {
201
- rootPath: string;
202
- noBuild: boolean;
203
- confFileRelPath: string;
204
- optNames: string[];
205
- pkgNames: string[]
206
- }): Promise<void> {
207
- const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "publishAsync"]);
229
+ logger.debug("빌드 프로세스 닫기...");
230
+ this._closeCluster(cluster);
208
231
 
209
- logger.debug("프로젝트 설정 가져오기...");
210
- const projConf = await SdCliConfigUtil.loadConfigAsync(path.resolve(opt.rootPath, opt.confFileRelPath), false, opt.optNames);
232
+ this._logging(results, logger);
233
+ }
211
234
 
212
- logger.debug("프로젝트 package.json 가져오기...");
213
- const projNpmConf = FsUtil.readJson(path.resolve(opt.rootPath, "package.json"));
235
+ public static async publishAsync(opt: {
236
+ noBuild: boolean;
237
+ confFileRelPath: string;
238
+ optNames: string[];
239
+ pkgNames: string[];
240
+ withLint: boolean;
241
+ }): Promise<void> {
242
+ const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "publishAsync"]);
214
243
 
215
- if (opt.noBuild) {
216
- logger.warn("빌드하지 않고, 배포하는것은 상당히 위험합니다.");
217
- await this._waitSecMessageAsync("프로세스를 중지하려면, 'CTRL+C'를 누르세요.", 5);
218
- }
244
+ logger.debug("프로젝트 설정 가져오기...");
245
+ const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(false, opt.optNames) as ISdCliConfig;
219
246
 
220
- // GIT 사용중일 경우, 커밋되지 않은 수정사항이 있는지 확인
221
- if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
222
- logger.debug("GIT 커밋여부 확인...");
223
- const gitStatusResult = await SdProcess.spawnAsync("git status");
224
- if (gitStatusResult.includes("Changes") || gitStatusResult.includes("Untracked")) {
225
- throw new Error("커밋되지 않은 정보가 있습니다.\n" + gitStatusResult);
226
- }
227
- }
247
+ logger.debug("프로젝트 package.json 가져오기...");
248
+ const projNpmConf = (await FsUtil.readJsonAsync(path.resolve(process.cwd(), "package.json"))) as INpmConfig;
228
249
 
229
- logger.debug("패키지 목록 구성...");
230
- const allPkgPaths = await projNpmConf.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
231
- let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
232
- if (opt.pkgNames.length !== 0) {
233
- pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
234
- }
250
+ if (opt.noBuild) {
251
+ logger.warn("빌드하지 않고, 배포하는것은 상당히 위험합니다.");
252
+ await this._waitSecMessageAsync("프로세스를 중지하려면, 'CTRL+C'를 누르세요.", 5);
253
+ }
235
254
 
236
- logger.debug("프로젝트 패키지 버전 설정...");
237
- await this._upgradeVersionAsync(opt.rootPath, projNpmConf, allPkgPaths);
255
+ // GIT 사용중일 경우, 커밋되지 않은 수정사항이 있는지 확인
256
+ if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
257
+ logger.debug("GIT 커밋여부 확인...");
258
+ const gitStatusResult = await SdProcess.spawnAsync("git status");
259
+ if (gitStatusResult.includes("Changes") || gitStatusResult.includes("Untracked")) {
260
+ throw new Error("커밋되지 않은 정보가 있습니다.\n" + gitStatusResult);
261
+ }
262
+ }
238
263
 
239
- // 빌드
240
- if (!opt.noBuild) {
241
- logger.debug("빌드 프로세스 준비...");
242
- const cluster = await this._prepareClusterAsync();
264
+ logger.debug("패키지 목록 구성...");
265
+ if (!projNpmConf.workspaces) {
266
+ throw new Error("프로젝트 package.json에 workspaces가 설정되어있지 않습니다.");
267
+ }
268
+ const allPkgPaths = await projNpmConf.workspaces.mapManyAsync(async (item) => await FsUtil.globAsync(item));
269
+ let pkgPaths = allPkgPaths.filter((pkgPath) => path.basename(pkgPath) in projConf.packages);
270
+ if (opt.pkgNames.length !== 0) {
271
+ pkgPaths = pkgPaths.filter((pkgPath) => opt.pkgNames.includes(path.basename(pkgPath)));
272
+ }
243
273
 
244
- logger.debug("빌드 프로세스 명령 전달...");
245
- const results = (
246
- await pkgPaths.parallelAsync(async (pkgPath) => {
247
- return await this._runCommandAsync(cluster, "build", pkgPath, projConf.packages[path.basename(pkgPath)]!);
248
- })
249
- ).mapMany();
274
+ logger.debug("프로젝트 패키지 버전 설정...");
275
+ await this._upgradeVersionAsync(projNpmConf, allPkgPaths);
250
276
 
251
- logger.debug("빌드 프로세스 닫기...");
252
- this._closeCluster(cluster);
277
+ // 빌드
278
+ if (!opt.noBuild) {
279
+ logger.debug("빌드 프로세스 준비...");
280
+ const cluster = await this._prepareClusterAsync();
253
281
 
254
- this._logging(results, logger);
255
- }
282
+ logger.debug("빌드 프로세스 명령 전달...");
283
+ const results = (
284
+ await pkgPaths.parallelAsync(async (pkgPath) => {
285
+ return await this._runCommandAsync(cluster, "build", pkgPath, projConf.packages[path.basename(pkgPath)]!, opt.withLint);
286
+ })
287
+ ).mapMany();
256
288
 
257
- // GIT 사용중일경우, 새 버전 커밋 및 TAG 생성
258
- if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
259
- logger.debug("새 버전 커밋 및 TAG 생성...");
260
- await SdProcess.spawnAsync("git add .");
261
- await SdProcess.spawnAsync(`git commit -m "v${projNpmConf.version}"`);
262
- await SdProcess.spawnAsync(`git tag -a "v${projNpmConf.version}" -m "v${projNpmConf.version}"`);
289
+ logger.debug("빌드 프로세스 닫기...");
290
+ this._closeCluster(cluster);
263
291
 
264
- logger.debug("새 버전 푸쉬...");
265
- await SdProcess.spawnAsync("git push");
266
- await SdProcess.spawnAsync("git push --tags");
267
- }
292
+ this._logging(results, logger);
293
+ }
268
294
 
269
- logger.debug("배포 시작...");
270
- await pkgPaths.parallelAsync(async (pkgPath) => {
271
- const pkgName = path.basename(pkgPath);
272
- const pkgConf = projConf.packages[pkgName];
273
- if (pkgConf?.publish == null) return;
295
+ // GIT 사용중일경우, 새 버전 커밋 및 TAG 생성
296
+ if (FsUtil.exists(path.resolve(process.cwd(), ".git"))) {
297
+ logger.debug("새 버전 커밋 및 TAG 생성...");
298
+ await SdProcess.spawnAsync("git add .");
299
+ await SdProcess.spawnAsync(`git commit -m "v${projNpmConf.version}"`);
300
+ await SdProcess.spawnAsync(`git tag -a "v${projNpmConf.version}" -m "v${projNpmConf.version}"`);
274
301
 
275
- logger.debug(`[${pkgName}] 배포 시작...`);
276
- await this._publishPkgAsync(pkgPath, pkgConf.publish);
277
- logger.debug(`[${pkgName}] 배포 완료`);
278
- });
302
+ logger.debug("새 버전 푸쉬...");
303
+ await SdProcess.spawnAsync("git push");
304
+ await SdProcess.spawnAsync("git push --tags");
305
+ }
279
306
 
280
- logger.info(`모든 배포가 완료되었습니다. (v${projNpmConf.version})`);
281
- }
307
+ logger.debug("배포 시작...");
308
+ await pkgPaths.parallelAsync(async (pkgPath) => {
309
+ const pkgName = path.basename(pkgPath);
310
+ const pkgConf = projConf.packages[pkgName];
311
+ if (pkgConf?.publish == null) return;
282
312
 
283
- private static async _publishPkgAsync(pkgPath: string, pkgPubConf: TSdCliPackageConfig["publish"]): Promise<void> {
284
- if (pkgPubConf === "npm") {
285
- await SdProcess.spawnAsync("yarn npm publish --access public", { cwd: pkgPath });
286
- }
287
- else {
288
- throw new NotImplementError();
289
- }
290
- }
313
+ logger.debug(`[${pkgName}] 배포 시작...`);
314
+ await this._publishPkgAsync(pkgPath, pkgConf.publish);
315
+ logger.debug(`[${pkgName}] 배포 완료`);
316
+ });
291
317
 
292
- private static async _waitSecMessageAsync(msg: string, sec: number): Promise<void> {
293
- for (let i = sec; i > 0; i--) {
294
- if (i !== sec) {
295
- process.stdout.cursorTo(0);
296
- }
297
- process.stdout.write(`${msg} ${i}`);
298
- await Wait.time(1000);
318
+ logger.info(`모든 배포가 완료되었습니다. (v${projNpmConf.version})`);
299
319
  }
300
320
 
301
- process.stdout.cursorTo(0);
302
- process.stdout.clearLine(0);
303
- }
304
-
305
- private static async _upgradeVersionAsync(projPath: string, projNpmConf: INpmConfig, allPkgPaths: string[]): Promise<void> {
306
- // 작업공간 package.json 버전 설정
307
- const newVersion = semver.inc(projNpmConf.version, "patch")!;
308
- projNpmConf.version = newVersion;
309
-
310
- const pkgNames = await allPkgPaths.mapAsync(async (pkgPath) => {
311
- const pkgNpmConf = await FsUtil.readJsonAsync(path.resolve(pkgPath, "package.json"));
312
- return pkgNpmConf.name;
313
- });
314
-
315
- const updateDepVersion = (deps: Record<string, string> | undefined): void => {
316
- if (!deps) return;
317
- for (const depName of Object.keys(deps)) {
318
- if (pkgNames.includes(depName)) {
319
- deps[depName] = newVersion;
321
+ private static async _publishPkgAsync(pkgPath: string, pkgPubConf: TSdCliPackageConfig["publish"]): Promise<void> {
322
+ if (pkgPubConf === "npm") {
323
+ await SdProcess.spawnAsync("yarn npm publish --access public", {cwd: pkgPath});
324
+ } else {
325
+ throw new NotImplementError();
320
326
  }
321
- }
322
- };
323
- updateDepVersion(projNpmConf.dependencies);
324
- updateDepVersion(projNpmConf.optionalDependencies);
325
- updateDepVersion(projNpmConf.devDependencies);
326
- updateDepVersion(projNpmConf.peerDependencies);
327
-
328
- const projNpmConfFilePath = path.resolve(projPath, "package.json");
329
- await FsUtil.writeJsonAsync(projNpmConfFilePath, projNpmConf, { space: 2 });
330
-
331
- // 각 패키지 package.json 버전 설정
332
- await allPkgPaths.parallelAsync(async (pkgPath) => {
333
- const pkgNpmConfFilePath = path.resolve(pkgPath, "package.json");
334
- const pkgNpmConf = await FsUtil.readJsonAsync(pkgNpmConfFilePath);
335
- pkgNpmConf.version = newVersion;
336
-
337
- updateDepVersion(pkgNpmConf.dependencies);
338
- updateDepVersion(pkgNpmConf.optionalDependencies);
339
- updateDepVersion(pkgNpmConf.devDependencies);
340
- updateDepVersion(pkgNpmConf.peerDependencies);
341
-
342
- await FsUtil.writeJsonAsync(pkgNpmConfFilePath, pkgNpmConf, { space: 2 });
343
- });
344
- }
345
-
346
- private static _logging(buildResults: ISdCliPackageBuildResult[], logger: Logger): void {
347
- const messages = buildResults.filter((item) => item.severity === "message");
348
- const suggestions = buildResults.filter((item) => item.severity === "suggestion");
349
- const warnings = buildResults.filter((item) => item.severity === "warning");
350
- const errors = buildResults.filter((item) => item.severity === "error");
351
-
352
- if (messages.length > 0) {
353
- logger.log("\n" + messages.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
354
- }
355
- if (suggestions.length > 0) {
356
- logger.info("\n" + suggestions.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
357
- }
358
- if (warnings.length > 0) {
359
- logger.warn("\n" + warnings.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
360
327
  }
361
- if (errors.length > 0) {
362
- logger.error("\n" + errors.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
363
- }
364
-
365
- logger.info("모든 빌드가 완료되었습니다.");
366
- }
367
328
 
368
- private static async _prepareClusterAsync(): Promise<cp.ChildProcess> {
369
- const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "_runBuildClusterAsync"]);
370
-
371
- return await new Promise<cp.ChildProcess>(async (resolve, reject) => {
372
- const cluster = cp.fork(
373
- fileURLToPath(await import.meta.resolve!("../build-cluster")),
374
- [],
375
- {
376
- stdio: ["pipe", "pipe", "pipe", "ipc"],
377
- env: process.env
329
+ private static async _waitSecMessageAsync(msg: string, sec: number): Promise<void> {
330
+ for (let i = sec; i > 0; i--) {
331
+ if (i !== sec) {
332
+ process.stdout.cursorTo(0);
333
+ }
334
+ process.stdout.write(`${msg} ${i}`);
335
+ await Wait.time(1000);
378
336
  }
379
- );
380
337
 
381
- cluster.stdout!.pipe(process.stdout);
382
- cluster.stderr!.pipe(process.stderr);
338
+ process.stdout.cursorTo(0);
339
+ process.stdout.clearLine(0);
340
+ }
383
341
 
384
- cluster.on("exit", (code) => {
385
- if (code != null && code !== 0) {
386
- const err = new Error(`오류와 함께 닫힘 (${code})`);
387
- logger.error(err);
388
- reject(err);
389
- return;
390
- }
391
- });
342
+ private static async _upgradeVersionAsync(projNpmConf: INpmConfig, allPkgPaths: string[]): Promise<void> {
343
+ // 작업공간 package.json 버전 설정
344
+ const newVersion = semver.inc(projNpmConf.version, "patch")!;
345
+ projNpmConf.version = newVersion;
346
+
347
+ const pkgNames = await allPkgPaths.mapAsync(async (pkgPath) => {
348
+ const pkgNpmConf = await FsUtil.readJsonAsync(path.resolve(pkgPath, "package.json"));
349
+ return pkgNpmConf.name;
350
+ });
351
+
352
+ const updateDepVersion = (deps: Record<string, string> | undefined): void => {
353
+ if (!deps) return;
354
+ for (const depName of Object.keys(deps)) {
355
+ if (pkgNames.includes(depName)) {
356
+ deps[depName] = newVersion;
357
+ }
358
+ }
359
+ };
360
+ updateDepVersion(projNpmConf.dependencies);
361
+ updateDepVersion(projNpmConf.optionalDependencies);
362
+ updateDepVersion(projNpmConf.devDependencies);
363
+ updateDepVersion(projNpmConf.peerDependencies);
364
+
365
+ const projNpmConfFilePath = path.resolve(process.cwd(), "package.json");
366
+ await FsUtil.writeJsonAsync(projNpmConfFilePath, projNpmConf, {space: 2});
367
+
368
+ // 각 패키지 package.json 버전 설정
369
+ await allPkgPaths.parallelAsync(async (pkgPath) => {
370
+ const pkgNpmConfFilePath = path.resolve(pkgPath, "package.json");
371
+ const pkgNpmConf = await FsUtil.readJsonAsync(pkgNpmConfFilePath);
372
+ pkgNpmConf.version = newVersion;
373
+
374
+ updateDepVersion(pkgNpmConf.dependencies);
375
+ updateDepVersion(pkgNpmConf.optionalDependencies);
376
+ updateDepVersion(pkgNpmConf.devDependencies);
377
+ updateDepVersion(pkgNpmConf.peerDependencies);
378
+
379
+ await FsUtil.writeJsonAsync(pkgNpmConfFilePath, pkgNpmConf, {space: 2});
380
+ });
381
+ }
392
382
 
393
- cluster.on("error", (err) => {
394
- logger.error(err);
395
- reject(err);
396
- });
383
+ private static _logging(buildResults: ISdCliPackageBuildResult[], logger: Logger): void {
384
+ const messages = buildResults.filter((item) => item.severity === "message");
385
+ const suggestions = buildResults.filter((item) => item.severity === "suggestion");
386
+ const warnings = buildResults.filter((item) => item.severity === "warning");
387
+ const errors = buildResults.filter((item) => item.severity === "error");
397
388
 
398
- cluster.on("message", (message) => {
399
- if (message === "ready") {
400
- logger.debug("빌드 클러스터 프로세스가 준비되었습니다.");
401
- resolve(cluster);
389
+ if (messages.length > 0) {
390
+ logger.log("\n" + messages.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
391
+ }
392
+ if (suggestions.length > 0) {
393
+ logger.info("\n" + suggestions.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
402
394
  }
403
- });
404
- });
405
- }
406
-
407
- private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "watch", pkgPath: string, pkgConf: TSdCliPackageConfig): Promise<void>;
408
- private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "build", pkgPath: string, pkgConf: TSdCliPackageConfig): Promise<ISdCliPackageBuildResult[]>;
409
- private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "watch" | "build", pkgPath: string, pkgConf: TSdCliPackageConfig): Promise<ISdCliPackageBuildResult[] | void> {
410
- return await new Promise<ISdCliPackageBuildResult[] | void>((resolve) => {
411
- const cb = (message: ISdCliBuildClusterResMessage): void => {
412
- if (cmd === "watch" && message.type === "ready" && message.req.cmd === cmd && message.req.pkgPath === pkgPath) {
413
- cluster.off("message", cb);
414
- resolve();
395
+ if (warnings.length > 0) {
396
+ logger.warn("\n" + warnings.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
415
397
  }
416
- else if (cmd === "build" && message.type === "complete" && message.req.cmd === cmd && message.req.pkgPath === pkgPath) {
417
- cluster.off("message", cb);
418
- resolve(message.result?.buildResults);
398
+ if (errors.length > 0) {
399
+ logger.error("\n" + errors.map((item) => SdCliBuildResultUtil.getMessage(item)).join("\n"));
419
400
  }
420
- };
421
- cluster.on("message", cb);
422
401
 
423
- cluster.send({ cmd, pkgPath, pkgConf } as ISdCliBuildClusterReqMessage);
424
- });
425
- }
402
+ logger.info("모든 빌드가 완료되었습니다.");
403
+ }
404
+
405
+ private static async _prepareClusterAsync(): Promise<cp.ChildProcess> {
406
+ const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "_runBuildClusterAsync"]);
426
407
 
427
- private static _closeCluster(cluster: cp.ChildProcess): void {
428
- cluster.kill("SIGKILL");
429
- }
408
+ return await new Promise<cp.ChildProcess>(async (resolve, reject) => {
409
+ const cluster = cp.fork(
410
+ fileURLToPath(await import.meta.resolve!("../build-cluster")),
411
+ [],
412
+ {
413
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
414
+ env: process.env
415
+ }
416
+ );
430
417
 
431
- private static async _restartServerAsync(pkgPath: string, prevServerProcess?: cp.ChildProcess): Promise<{ worker: cp.ChildProcess, port: number }> {
432
- const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "_restartServerAsync"]);
418
+ cluster.stdout!.pipe(process.stdout);
419
+ cluster.stderr!.pipe(process.stderr);
420
+
421
+ cluster.on("exit", (code) => {
422
+ if (code != null && code !== 0) {
423
+ const err = new Error(`오류와 함께 닫힘 (${code})`);
424
+ logger.error(err);
425
+ reject(err);
426
+ return;
427
+ }
428
+ });
433
429
 
434
- if (prevServerProcess) {
435
- prevServerProcess.kill("SIGKILL");
430
+ cluster.on("error", (err) => {
431
+ logger.error(err);
432
+ reject(err);
433
+ });
434
+
435
+ cluster.on("message", (message) => {
436
+ if (message === "ready") {
437
+ logger.debug("빌드 클러스터 프로세스가 준비되었습니다.");
438
+ resolve(cluster);
439
+ }
440
+ });
441
+ });
436
442
  }
437
443
 
438
- return await new Promise<{ worker: cp.ChildProcess, port: number }>(async (resolve, reject) => {
439
- const worker = cp.fork(
440
- fileURLToPath(await import.meta.resolve!("../server-worker")),
441
- [pkgPath],
442
- {
443
- stdio: ["pipe", "pipe", "pipe", "ipc"],
444
- env: process.env
445
- }
446
- );
444
+ private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "watch", pkgPath: string, pkgConf: TSdCliPackageConfig, withLint: boolean, builderKey?: string): Promise<void>;
445
+ private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "build", pkgPath: string, pkgConf: TSdCliPackageConfig, withLint: boolean, builderKey?: string): Promise<ISdCliPackageBuildResult[]>;
446
+ private static async _runCommandAsync(cluster: cp.ChildProcess, cmd: "watch" | "build", pkgPath: string, pkgConf: TSdCliPackageConfig, withLint: boolean, builderKey?: string): Promise<ISdCliPackageBuildResult[] | void> {
447
+ return await new Promise<ISdCliPackageBuildResult[] | void>((resolve) => {
448
+ const cb = (message: ISdCliBuildClusterResMessage): void => {
449
+ if (cmd === "watch" && message.type === "ready" && message.req.cmd === cmd && message.req.pkgPath === pkgPath) {
450
+ cluster.off("message", cb);
451
+ resolve();
452
+ } else if (cmd === "build" && message.type === "complete" && message.req.cmd === cmd && message.req.pkgPath === pkgPath) {
453
+ cluster.off("message", cb);
454
+ resolve(message.result?.buildResults);
455
+ }
456
+ };
457
+ cluster.on("message", cb);
458
+
459
+ cluster.send({
460
+ cmd,
461
+ pkgPath,
462
+ pkgConf,
463
+ builderKey,
464
+ withLint
465
+ } as ISdCliBuildClusterReqMessage);
466
+ });
467
+ }
468
+
469
+ private static _closeCluster(cluster: cp.ChildProcess): void {
470
+ cluster.kill("SIGKILL");
471
+ }
447
472
 
448
- worker.stdout!.pipe(process.stdout);
449
- worker.stderr!.pipe(process.stderr);
473
+ private static async _restartServerAsync(pkgPath: string, prevServerProcess?: cp.ChildProcess): Promise<{
474
+ worker: cp.ChildProcess,
475
+ port: number
476
+ }> {
477
+ const logger = Logger.get(["simplysm", "sd-cli", "SdCliProject", "_restartServerAsync"]);
450
478
 
451
- worker.on("exit", (code) => {
452
- if (code != null && code !== 0) {
453
- const err = new Error(`오류와 함께 닫힘 (${code})`);
454
- logger.error(err);
455
- reject(err);
456
- return;
479
+ if (prevServerProcess) {
480
+ prevServerProcess.kill("SIGKILL");
457
481
  }
458
- });
459
482
 
460
- worker.on("error", (err) => {
461
- logger.error(err);
462
- reject(err);
463
- });
483
+ return await new Promise<{
484
+ worker: cp.ChildProcess,
485
+ port: number
486
+ }>(async (resolve, reject) => {
487
+ const worker = cp.fork(
488
+ fileURLToPath(await import.meta.resolve!("../server-worker")),
489
+ [pkgPath],
490
+ {
491
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
492
+ env: process.env
493
+ }
494
+ );
464
495
 
465
- worker.on("message", (message: any) => {
466
- if ("port" in message) {
467
- logger.debug("서버가 시작되었습니다.");
468
- resolve({ worker, port: message.port });
469
- }
470
- });
471
- });
472
- }
496
+ worker.stdout!.pipe(process.stdout);
497
+ worker.stderr!.pipe(process.stderr);
498
+
499
+ worker.on("exit", (code) => {
500
+ if (code != null && code !== 0) {
501
+ const err = new Error(`오류와 함께 닫힘 (${code})`);
502
+ logger.error(err);
503
+ reject(err);
504
+ return;
505
+ }
506
+ });
507
+
508
+ worker.on("error", (err) => {
509
+ logger.error(err);
510
+ reject(err);
511
+ });
512
+
513
+ worker.on("message", (message: any) => {
514
+ if ("port" in message) {
515
+ logger.debug("서버가 시작되었습니다.");
516
+ resolve({
517
+ worker,
518
+ port: message.port
519
+ });
520
+ }
521
+ });
522
+ });
523
+ }
473
524
  }