@simplysm/sd-cli 7.0.37 → 7.0.38

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.
@@ -10,6 +10,7 @@ import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
10
10
  import { SdServiceServer } from "@simplysm/sd-service/server";
11
11
  import { SdCliNpm } from "./SdCliNpm";
12
12
  import { SdCliLocalUpdate } from "./SdCliLocalUpdate";
13
+ import { NextHandleFunction } from "connect";
13
14
 
14
15
  export class SdCliWorkspace {
15
16
  private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
@@ -47,11 +48,7 @@ export class SdCliWorkspace {
47
48
  this._logger.debug(`[${pkg.name}] 빌드를 시작합니다...`);
48
49
  })
49
50
  .on("complete", async (results) => {
50
- if (pkg.type === "server") {
51
- if (results.some((item) => item.severity === "error")) {
52
- return;
53
- }
54
-
51
+ if (pkg.config.type === "server" && !results.some((item) => item.severity === "error")) {
55
52
  await this._restartServerAsync(pkg);
56
53
  }
57
54
 
@@ -62,6 +59,7 @@ export class SdCliWorkspace {
62
59
  changeCount--;
63
60
  if (changeCount === 0) {
64
61
  this._loggingResults(totalResultMap);
62
+ this._loggingOpenClientHrefs();
65
63
  this._logger.info("모든 빌드가 완료되었습니다.");
66
64
  }
67
65
  }, 500);
@@ -73,7 +71,16 @@ export class SdCliWorkspace {
73
71
  const buildCompletedPackageNames: string[] = [];
74
72
  await pkgs.parallelAsync(async (pkg) => {
75
73
  await Wait.until(() => !pkg.allDependencies.some((dep) => pkgNames.includes(dep) && !buildCompletedPackageNames.includes(dep)));
76
- await pkg.watchAsync();
74
+ if (pkg.config.type === "client") {
75
+ const middlewares = (await pkg.watchAsync()) as NextHandleFunction[];
76
+
77
+ const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { middlewares: [], clientInfos: [] });
78
+ serverInfo.middlewares.push(...middlewares);
79
+ serverInfo.clientInfos.push({ pkgKey: pkg.name.split("/").last()! });
80
+ }
81
+ else {
82
+ await pkg.watchAsync();
83
+ }
77
84
  buildCompletedPackageNames.push(pkg.name);
78
85
  });
79
86
  }
@@ -87,21 +94,26 @@ export class SdCliWorkspace {
87
94
  const entryFilePath = path.resolve(pkg.rootPath, entryFileRelPath);
88
95
 
89
96
  this._logger.log(`서버(${pkg.name}) 재시작...`);
90
- const serverInfo = this._serverInfoMap.getOrCreate(pkg.name, {});
91
- if (serverInfo.server) {
92
- await serverInfo.server.closeAsync();
93
- delete serverInfo.server;
94
- }
95
-
96
- serverInfo.server = (await import("file:///" + entryFilePath + "?update=" + Uuid.new().toString())).default as SdServiceServer | undefined;
97
- if (!serverInfo.server) {
98
- this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
99
- return;
100
- }
97
+ try {
98
+ const serverInfo = this._serverInfoMap.getOrCreate(pkg.name, { middlewares: [], clientInfos: [] });
99
+ if (serverInfo.server) {
100
+ await serverInfo.server.closeAsync();
101
+ delete serverInfo.server;
102
+ }
101
103
 
102
- await Wait.until(() => serverInfo.server!.isOpen);
104
+ serverInfo.server = (await import("file:///" + entryFilePath + "?update=" + Uuid.new().toString())).default as SdServiceServer | undefined;
105
+ if (!serverInfo.server) {
106
+ this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
107
+ return;
108
+ }
109
+ serverInfo.server.devMiddlewares = serverInfo.middlewares;
110
+ await Wait.until(() => serverInfo.server!.isOpen);
103
111
 
104
- this._logger.log(`서버(${pkg.name}) 재시작 완료`);
112
+ this._logger.log(`서버(${pkg.name}) 재시작 완료`);
113
+ }
114
+ catch (err) {
115
+ this._logger.error(`서버(${pkg.name}) 재시작중 오류 발생`, err);
116
+ }
105
117
  }
106
118
 
107
119
  public async buildAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
@@ -278,8 +290,29 @@ export class SdCliWorkspace {
278
290
  this._logger.warn(`경고: ${warnings.length}건, 오류: ${errors.length}건`);
279
291
  }
280
292
  }
293
+
294
+ private _loggingOpenClientHrefs(): void {
295
+ const clientHrefs: string[] = [];
296
+
297
+ const serverInfos = Array.from(this._serverInfoMap.values());
298
+ for (const serverInfo of serverInfos) {
299
+ if (!serverInfo.server) continue;
300
+
301
+ const protocolStr = serverInfo.server.options.ssl ? "https" : "http";
302
+ const portStr = serverInfo.server.options.port.toString();
303
+
304
+ for (const clientInfo of serverInfo.clientInfos) {
305
+ clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/`);
306
+ }
307
+ }
308
+ if (clientHrefs.length > 0) {
309
+ this._logger.log(`오픈된 클라이언트: ${clientHrefs.join(", ")}`);
310
+ }
311
+ }
281
312
  }
282
313
 
283
314
  interface IServerInfo {
284
315
  server?: SdServiceServer;
316
+ middlewares: NextHandleFunction[];
317
+ clientInfos: { pkgKey: string }[];
285
318
  }
@@ -7,6 +7,8 @@ import { SdCliTsLibBuilder } from "../builder/SdCliTsLibBuilder";
7
7
  import { SdCliJsLibBuilder } from "../builder/SdCliJsLibBuilder";
8
8
  import { SdCliServerBuilder } from "../builder/SdCliServerBuilder";
9
9
  import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
10
+ import { SdCliClientBuilder } from "../builder/SdCliClientBuilder";
11
+ import { NextHandleFunction } from "connect";
10
12
 
11
13
  export class SdCliPackage extends EventEmitter {
12
14
  private readonly _npmConfig: INpmConfig;
@@ -23,10 +25,6 @@ export class SdCliPackage extends EventEmitter {
23
25
  return this._npmConfig.main;
24
26
  }
25
27
 
26
- public get type(): TSdCliPackageConfig["type"] {
27
- return this._config.type;
28
- }
29
-
30
28
  public get allDependencies(): string[] {
31
29
  return [
32
30
  ...SdCliNpmConfigUtil.getDependencies(this._npmConfig).defaults,
@@ -36,7 +34,7 @@ export class SdCliPackage extends EventEmitter {
36
34
 
37
35
  public constructor(private readonly _workspaceRootPath: string,
38
36
  public readonly rootPath: string,
39
- private readonly _config: TSdCliPackageConfig) {
37
+ public readonly config: TSdCliPackageConfig) {
40
38
  super();
41
39
 
42
40
  const npmConfigFilePath = path.resolve(this.rootPath, "package.json");
@@ -69,8 +67,8 @@ export class SdCliPackage extends EventEmitter {
69
67
  await FsUtil.writeJsonAsync(npmConfigFilePath, this._npmConfig, { space: 2 });
70
68
  }
71
69
 
72
- public async watchAsync(): Promise<void> {
73
- await (await this._createBuilderAsync())
70
+ public async watchAsync(): Promise<NextHandleFunction[] | void> {
71
+ return await (await this._createBuilderAsync())
74
72
  .on("change", () => {
75
73
  this.emit("change");
76
74
  })
@@ -85,24 +83,27 @@ export class SdCliPackage extends EventEmitter {
85
83
  }
86
84
 
87
85
  public async publishAsync(): Promise<void> {
88
- if (this._config.type === "library" && this._config.publish === "npm") {
86
+ if (this.config.type === "library" && this.config.publish === "npm") {
89
87
  await SdProcess.spawnAsync("npm publish --quiet --access public", { cwd: this.rootPath });
90
88
  }
91
89
  }
92
90
 
93
- private async _createBuilderAsync(): Promise<SdCliJsLibBuilder | SdCliTsLibBuilder | SdCliServerBuilder> {
91
+ private async _createBuilderAsync(): Promise<SdCliJsLibBuilder | SdCliTsLibBuilder | SdCliServerBuilder | SdCliClientBuilder> {
94
92
  const isTs = FsUtil.exists(path.resolve(this.rootPath, "tsconfig.json"));
95
93
 
96
94
  if (isTs) {
97
95
  await this._genBuildTsconfigAsync();
98
96
  }
99
97
 
100
- if (this._config.type === "library") {
98
+ if (this.config.type === "library") {
101
99
  // const isAngular = isTs && this.allDependencies.includes("@angular/core");
102
100
  return isTs ? new SdCliTsLibBuilder(this.rootPath) : new SdCliJsLibBuilder(this.rootPath);
103
101
  }
102
+ else if (this.config.type === "server") {
103
+ return new SdCliServerBuilder(this.rootPath, this.config, this._workspaceRootPath);
104
+ }
104
105
  else {
105
- return new SdCliServerBuilder(this.rootPath, this._config, this._workspaceRootPath);
106
+ return new SdCliClientBuilder(this.rootPath, this.config, this._workspaceRootPath);
106
107
  }
107
108
  }
108
109
 
@@ -49,8 +49,8 @@ export class SdCliBuildResultUtil {
49
49
  private static _convertFromWebpackError(severity: "warning" | "error", err: webpack.WebpackError): ISdCliPackageBuildResult {
50
50
  return {
51
51
  filePath: err.file,
52
- line: err.loc["start"].line,
53
- char: err.loc["start"].column,
52
+ line: err.file ? err.loc["start"]?.line : undefined,
53
+ char: err.file ? err.loc["start"]?.column : undefined,
54
54
  code: err.name,
55
55
  severity,
56
56
  message: err.message