@simplysm/sd-cli 7.0.22 → 7.0.26
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.
- package/dist/bin/sd-cli.d.ts +1 -1
- package/dist/bin/sd-cli.mjs +52 -15
- package/dist/builder/SdCliServerBuilder.d.ts +22 -0
- package/dist/builder/SdCliServerBuilder.mjs +323 -0
- package/dist/builder/SdCliTsLibBuilder.mjs +2 -2
- package/dist/commons.d.ts +5 -4
- package/dist/entry-points/SdCliLocalUpdate.d.ts +7 -4
- package/dist/entry-points/SdCliLocalUpdate.mjs +6 -7
- package/dist/entry-points/SdCliNpm.d.ts +6 -0
- package/dist/entry-points/SdCliNpm.mjs +18 -0
- package/dist/entry-points/SdCliPrepare.d.ts +5 -0
- package/dist/entry-points/SdCliPrepare.mjs +54 -0
- package/dist/entry-points/SdCliWorkspace.d.ts +13 -5
- package/dist/entry-points/SdCliWorkspace.mjs +49 -13
- package/dist/packages/SdCliPackage.d.ts +6 -2
- package/dist/packages/SdCliPackage.mjs +34 -23
- package/dist/utils/SdCliBuildResultUtil.d.ts +4 -1
- package/dist/utils/SdCliBuildResultUtil.mjs +24 -2
- package/dist/utils/SdCliConfigUtil.d.ts +1 -1
- package/dist/utils/SdCliConfigUtil.mjs +5 -5
- package/package.json +13 -5
- package/src/bin/sd-cli.ts +59 -14
- package/src/builder/SdCliServerBuilder.ts +359 -0
- package/src/builder/SdCliTsLibBuilder.ts +1 -1
- package/src/commons.ts +3 -5
- package/src/entry-points/SdCliLocalUpdate.ts +5 -6
- package/src/entry-points/SdCliNpm.ts +22 -0
- package/src/entry-points/SdCliPrepare.ts +54 -0
- package/src/entry-points/SdCliWorkspace.ts +65 -15
- package/src/packages/SdCliPackage.ts +37 -26
- package/src/utils/SdCliBuildResultUtil.ts +30 -1
- package/src/utils/SdCliConfigUtil.ts +4 -4
- package/tsconfig.json +4 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { FsUtil, Logger } from "@simplysm/sd-core-node";
|
|
2
|
+
|
|
3
|
+
export class SdCliPrepare {
|
|
4
|
+
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
5
|
+
|
|
6
|
+
public async prepareAsync(): Promise<void> {
|
|
7
|
+
// 타입체크 속도 지연 메시지 추가
|
|
8
|
+
const r1 = await this._modifyTypescriptCodeForTypeCheckPerformanceWarning();
|
|
9
|
+
this._logger.log(`[모듈수정] 타입체크 속도 지연 메시지 추가 (${r1 ? "O" : "X"})`);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
private async _modifyTypescriptCodeForTypeCheckPerformanceWarning(): Promise<boolean> {
|
|
13
|
+
const fileUrl = await import.meta.resolve!("typescript");
|
|
14
|
+
const filePath = fileUrl.replace(/^file:\/\/\//, "");
|
|
15
|
+
const fileContent = await FsUtil.readFileAsync(filePath);
|
|
16
|
+
const modifiedFileContent = fileContent.replace(`
|
|
17
|
+
function checkSourceElement(node) {
|
|
18
|
+
if (node) {
|
|
19
|
+
var saveCurrentNode = currentNode;
|
|
20
|
+
currentNode = node;
|
|
21
|
+
instantiationCount = 0;
|
|
22
|
+
checkSourceElementWorker(node);
|
|
23
|
+
currentNode = saveCurrentNode;
|
|
24
|
+
}
|
|
25
|
+
}`, `
|
|
26
|
+
function checkSourceElement(node) {
|
|
27
|
+
if (node) {
|
|
28
|
+
const prevUsage = process.cpuUsage();
|
|
29
|
+
|
|
30
|
+
var saveCurrentNode = currentNode;
|
|
31
|
+
currentNode = node;
|
|
32
|
+
instantiationCount = 0;
|
|
33
|
+
checkSourceElementWorker(node);
|
|
34
|
+
currentNode = saveCurrentNode;
|
|
35
|
+
|
|
36
|
+
const usage = process.cpuUsage(prevUsage);
|
|
37
|
+
if (node.hasChildPerformanceWarning) {
|
|
38
|
+
node.parent.hasChildPerformanceWarning = true;
|
|
39
|
+
}
|
|
40
|
+
else if (usage.user + usage.system > 2000 * 1000 && node.kind !== 253) {
|
|
41
|
+
error(node, {
|
|
42
|
+
code: 9000,
|
|
43
|
+
category: ts.DiagnosticCategory.Warning,
|
|
44
|
+
key: "simplysm_check_source_element_performance_slow",
|
|
45
|
+
message: "소스코드 타입분석에 너무 오랜 시간이 소요됩니다. [" + Math.round((usage.user + usage.system) / 1000) + "ms/cpu, KIND: " + node.kind + "]"
|
|
46
|
+
});
|
|
47
|
+
node.parent.hasChildPerformanceWarning = true;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}`);
|
|
51
|
+
await FsUtil.writeFileAsync(filePath, modifiedFileContent);
|
|
52
|
+
return fileContent !== modifiedFileContent;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -2,28 +2,31 @@ import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { INpmConfig, ISdCliConfig, ISdCliPackageBuildResult } from "../commons";
|
|
4
4
|
import { SdCliPackage } from "../packages/SdCliPackage";
|
|
5
|
-
import { Wait } from "@simplysm/sd-core-common";
|
|
5
|
+
import { Uuid, Wait } from "@simplysm/sd-core-common";
|
|
6
6
|
import os from "os";
|
|
7
7
|
import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
|
|
8
8
|
import semver from "semver/preload";
|
|
9
|
+
import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
|
|
10
|
+
import { SdServiceServer } from "@simplysm/sd-service/server";
|
|
11
|
+
import { SdCliNpm } from "./SdCliNpm";
|
|
9
12
|
|
|
10
13
|
export class SdCliWorkspace {
|
|
11
14
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
12
15
|
|
|
13
16
|
private readonly _npmConfig: INpmConfig;
|
|
14
|
-
private readonly
|
|
17
|
+
private readonly _serverInfoMap = new Map<string, IServerInfo>();
|
|
15
18
|
|
|
16
|
-
public constructor(private readonly _rootPath: string
|
|
17
|
-
private readonly _configFilePath?: string) {
|
|
19
|
+
public constructor(private readonly _rootPath: string) {
|
|
18
20
|
const npmConfigFilePath = path.resolve(this._rootPath, "package.json");
|
|
19
21
|
this._npmConfig = FsUtil.readJson(npmConfigFilePath);
|
|
20
|
-
|
|
21
|
-
this._config = FsUtil.readJson(path.resolve(this._rootPath, this._configFilePath ?? "simplysm.json"));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
public async watchAsync(): Promise<void> {
|
|
24
|
+
public async watchAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
25
|
+
this._logger.debug("프로젝트 설정 가져오기...");
|
|
26
|
+
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), true, opt.optNames);
|
|
27
|
+
|
|
25
28
|
this._logger.debug("패키지 목록 구성...");
|
|
26
|
-
const pkgs = await this._getPackagesAsync();
|
|
29
|
+
const pkgs = await this._getPackagesAsync(config);
|
|
27
30
|
|
|
28
31
|
this._logger.debug("패키지 이벤트 설정...");
|
|
29
32
|
let changeCount = 0;
|
|
@@ -37,7 +40,15 @@ export class SdCliWorkspace {
|
|
|
37
40
|
changeCount++;
|
|
38
41
|
this._logger.debug(`[${pkg.name}] 빌드를 시작합니다...`);
|
|
39
42
|
})
|
|
40
|
-
.on("complete", (results) => {
|
|
43
|
+
.on("complete", async (results) => {
|
|
44
|
+
if (pkg.type === "server") {
|
|
45
|
+
if (results.some((item) => item.severity === "error")) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
await this._restartServerAsync(pkg);
|
|
50
|
+
}
|
|
51
|
+
|
|
41
52
|
this._logger.debug(`[${pkg.name}] 빌드가 완료되었습니다.`);
|
|
42
53
|
totalResultMap.set(pkg.name, results);
|
|
43
54
|
|
|
@@ -61,9 +72,38 @@ export class SdCliWorkspace {
|
|
|
61
72
|
});
|
|
62
73
|
}
|
|
63
74
|
|
|
64
|
-
|
|
75
|
+
private async _restartServerAsync(pkg: SdCliPackage): Promise<void> {
|
|
76
|
+
const entryFileRelPath = pkg.main;
|
|
77
|
+
if (entryFileRelPath === undefined) {
|
|
78
|
+
this._logger.error(`서버패키지(${pkg.name})의 'package.json'에서 'main'필드를 찾을 수 없습니다.`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const entryFilePath = path.resolve(pkg.rootPath, entryFileRelPath);
|
|
82
|
+
|
|
83
|
+
this._logger.log(`서버(${pkg.name}) 재시작...`);
|
|
84
|
+
const serverInfo = this._serverInfoMap.getOrCreate(pkg.name, {});
|
|
85
|
+
if (serverInfo.server) {
|
|
86
|
+
await serverInfo.server.closeAsync();
|
|
87
|
+
delete serverInfo.server;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
serverInfo.server = (await import("file:///" + entryFilePath + "?update=" + Uuid.new().toString())).default as SdServiceServer | undefined;
|
|
91
|
+
if (!serverInfo.server) {
|
|
92
|
+
this._logger.error(`${entryFilePath}(0, 0): 'SdServiceServer'를 'export'해야 합니다.`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
await Wait.until(() => serverInfo.server!.isOpen);
|
|
97
|
+
|
|
98
|
+
this._logger.log(`서버(${pkg.name}) 재시작 완료`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public async buildAsync(opt: { confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
102
|
+
this._logger.debug("프로젝트 설정 가져오기...");
|
|
103
|
+
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
|
|
104
|
+
|
|
65
105
|
this._logger.debug("패키지 목록 구성...");
|
|
66
|
-
const pkgs = await this._getPackagesAsync();
|
|
106
|
+
const pkgs = await this._getPackagesAsync(config);
|
|
67
107
|
|
|
68
108
|
this._logger.debug("프로젝트 및 패키지 버전 설정...");
|
|
69
109
|
await this._upgradeVersionAsync(pkgs);
|
|
@@ -96,7 +136,10 @@ export class SdCliWorkspace {
|
|
|
96
136
|
}
|
|
97
137
|
}
|
|
98
138
|
|
|
99
|
-
public async publishAsync(opt: { noBuild: boolean }): Promise<void> {
|
|
139
|
+
public async publishAsync(opt: { noBuild: boolean; confFileRelPath: string; optNames: string[] }): Promise<void> {
|
|
140
|
+
this._logger.debug("프로젝트 설정 가져오기...");
|
|
141
|
+
const config = await SdCliConfigUtil.loadConfigAsync(path.resolve(this._rootPath, opt.confFileRelPath), false, opt.optNames);
|
|
142
|
+
|
|
100
143
|
if (opt.noBuild) {
|
|
101
144
|
this._logger.warn("빌드하지 않고, 배포하는것은 상당히 위험합니다.");
|
|
102
145
|
await this._waitSecMessageAsync("프로세스를 중지하려면, 'CTRL+C'를 누르세요.", 5);
|
|
@@ -112,11 +155,14 @@ export class SdCliWorkspace {
|
|
|
112
155
|
}
|
|
113
156
|
|
|
114
157
|
this._logger.debug("패키지 목록 구성...");
|
|
115
|
-
const pkgs = await this._getPackagesAsync();
|
|
158
|
+
const pkgs = await this._getPackagesAsync(config);
|
|
116
159
|
|
|
117
160
|
this._logger.debug("프로젝트 및 패키지 버전 설정...");
|
|
118
161
|
await this._upgradeVersionAsync(pkgs);
|
|
119
162
|
|
|
163
|
+
this._logger.debug("노드패키지 업데이트...");
|
|
164
|
+
await new SdCliNpm(this._rootPath).updateAsync();
|
|
165
|
+
|
|
120
166
|
// 빌드
|
|
121
167
|
if (!opt.noBuild) {
|
|
122
168
|
this._logger.debug("빌드를 시작합니다...");
|
|
@@ -182,14 +228,14 @@ export class SdCliWorkspace {
|
|
|
182
228
|
process.stdout.clearLine(0);
|
|
183
229
|
}
|
|
184
230
|
|
|
185
|
-
private async _getPackagesAsync(): Promise<SdCliPackage[]> {
|
|
231
|
+
private async _getPackagesAsync(conf: ISdCliConfig): Promise<SdCliPackage[]> {
|
|
186
232
|
const pkgRootPaths = await this._npmConfig.workspaces?.mapManyAsync(async (item) => await FsUtil.globAsync(item));
|
|
187
233
|
if (!pkgRootPaths) {
|
|
188
234
|
throw new Error("최상위 'package.json'에서 'workspaces'를 찾을 수 없습니다.");
|
|
189
235
|
}
|
|
190
236
|
|
|
191
237
|
return pkgRootPaths.map((pkgRootPath) => {
|
|
192
|
-
const pkgConfig =
|
|
238
|
+
const pkgConfig = conf.packages[path.basename(pkgRootPath)];
|
|
193
239
|
return pkgConfig ? new SdCliPackage(this._rootPath, pkgRootPath, pkgConfig) : undefined;
|
|
194
240
|
}).filterExists();
|
|
195
241
|
}
|
|
@@ -227,3 +273,7 @@ export class SdCliWorkspace {
|
|
|
227
273
|
}
|
|
228
274
|
}
|
|
229
275
|
}
|
|
276
|
+
|
|
277
|
+
interface IServerInfo {
|
|
278
|
+
server?: SdServiceServer;
|
|
279
|
+
}
|
|
@@ -5,29 +5,42 @@ import { EventEmitter } from "events";
|
|
|
5
5
|
import { ObjectUtil } from "@simplysm/sd-core-common";
|
|
6
6
|
import { SdCliTsLibBuilder } from "../builder/SdCliTsLibBuilder";
|
|
7
7
|
import { SdCliJsLibBuilder } from "../builder/SdCliJsLibBuilder";
|
|
8
|
+
import { SdCliServerBuilder } from "../builder/SdCliServerBuilder";
|
|
8
9
|
|
|
9
10
|
export class SdCliPackage extends EventEmitter {
|
|
10
11
|
private readonly _npmConfig: INpmConfig;
|
|
11
12
|
|
|
13
|
+
public get basename(): string {
|
|
14
|
+
return path.basename(this._workspaceRootPath);
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
public get name(): string {
|
|
13
18
|
return this._npmConfig.name;
|
|
14
19
|
}
|
|
15
20
|
|
|
21
|
+
public get main(): string | undefined {
|
|
22
|
+
return this._npmConfig.main;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
public get type(): TSdCliPackageConfig["type"] {
|
|
26
|
+
return this._config.type;
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
public get allDependencies(): string[] {
|
|
17
30
|
return [
|
|
18
31
|
...Object.keys(this._npmConfig.dependencies ?? {}),
|
|
19
32
|
...Object.keys(this._npmConfig.optionalDependencies ?? {}),
|
|
20
|
-
...Object.keys(this._npmConfig.devDependencies ?? {}),
|
|
33
|
+
// ...Object.keys(this._npmConfig.devDependencies ?? {}),
|
|
21
34
|
...Object.keys(this._npmConfig.peerDependencies ?? {})
|
|
22
35
|
].distinct();
|
|
23
36
|
}
|
|
24
37
|
|
|
25
38
|
public constructor(private readonly _workspaceRootPath: string,
|
|
26
|
-
|
|
39
|
+
public readonly rootPath: string,
|
|
27
40
|
private readonly _config: TSdCliPackageConfig) {
|
|
28
41
|
super();
|
|
29
42
|
|
|
30
|
-
const npmConfigFilePath = path.resolve(this.
|
|
43
|
+
const npmConfigFilePath = path.resolve(this.rootPath, "package.json");
|
|
31
44
|
this._npmConfig = FsUtil.readJson(npmConfigFilePath);
|
|
32
45
|
}
|
|
33
46
|
|
|
@@ -53,21 +66,12 @@ export class SdCliPackage extends EventEmitter {
|
|
|
53
66
|
updateDepVersion(this._npmConfig.devDependencies);
|
|
54
67
|
updateDepVersion(this._npmConfig.peerDependencies);
|
|
55
68
|
|
|
56
|
-
const npmConfigFilePath = path.resolve(this.
|
|
69
|
+
const npmConfigFilePath = path.resolve(this.rootPath, "package.json");
|
|
57
70
|
await FsUtil.writeJsonAsync(npmConfigFilePath, this._npmConfig, { space: 2 });
|
|
58
71
|
}
|
|
59
72
|
|
|
60
73
|
public async watchAsync(): Promise<void> {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (isTs) {
|
|
64
|
-
await this._genBuildTsconfigAsync();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const isAngular = isTs && this.allDependencies.includes("@angular/core");
|
|
68
|
-
const builder = !isTs ? new SdCliJsLibBuilder(this._rootPath) : new SdCliTsLibBuilder(this._rootPath, isAngular);
|
|
69
|
-
|
|
70
|
-
await builder
|
|
74
|
+
await (await this._createBuilderAsync())
|
|
71
75
|
.on("change", () => {
|
|
72
76
|
this.emit("change");
|
|
73
77
|
})
|
|
@@ -78,26 +82,33 @@ export class SdCliPackage extends EventEmitter {
|
|
|
78
82
|
}
|
|
79
83
|
|
|
80
84
|
public async buildAsync(): Promise<ISdCliPackageBuildResult[]> {
|
|
81
|
-
|
|
85
|
+
return await (await this._createBuilderAsync()).buildAsync();
|
|
86
|
+
}
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
public async publishAsync(): Promise<void> {
|
|
89
|
+
if (this._config.type === "library" && this._config.publish === "npm") {
|
|
90
|
+
await SdProcess.execAsync("npm publish --quiet --access public", { cwd: this.rootPath });
|
|
85
91
|
}
|
|
92
|
+
}
|
|
86
93
|
|
|
87
|
-
|
|
88
|
-
const
|
|
94
|
+
private async _createBuilderAsync(): Promise<SdCliJsLibBuilder | SdCliTsLibBuilder | SdCliServerBuilder> {
|
|
95
|
+
const isTs = FsUtil.exists(path.resolve(this.rootPath, "tsconfig.json"));
|
|
89
96
|
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
if (isTs) {
|
|
98
|
+
await this._genBuildTsconfigAsync();
|
|
99
|
+
}
|
|
92
100
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
if (this._config.type === "library") {
|
|
102
|
+
const isAngular = isTs && this.allDependencies.includes("@angular/core");
|
|
103
|
+
return isTs ? new SdCliTsLibBuilder(this.rootPath, isAngular) : new SdCliJsLibBuilder(this.rootPath);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return new SdCliServerBuilder(this.rootPath, this._config, this._workspaceRootPath);
|
|
96
107
|
}
|
|
97
108
|
}
|
|
98
109
|
|
|
99
110
|
private async _genBuildTsconfigAsync(): Promise<void> {
|
|
100
|
-
const baseTsconfigFilePath = path.resolve(this.
|
|
111
|
+
const baseTsconfigFilePath = path.resolve(this.rootPath, "tsconfig.json");
|
|
101
112
|
const baseTsconfig: ITsconfig = await FsUtil.readJsonAsync(baseTsconfigFilePath);
|
|
102
113
|
|
|
103
114
|
const buildTsconfig: ITsconfig = ObjectUtil.clone(baseTsconfig);
|
|
@@ -105,7 +116,7 @@ export class SdCliPackage extends EventEmitter {
|
|
|
105
116
|
delete buildTsconfig.compilerOptions.baseUrl;
|
|
106
117
|
delete buildTsconfig.compilerOptions.paths;
|
|
107
118
|
|
|
108
|
-
const buildTsconfigFilePath = path.resolve(this.
|
|
119
|
+
const buildTsconfigFilePath = path.resolve(this.rootPath, "tsconfig-build.json");
|
|
109
120
|
await FsUtil.writeJsonAsync(buildTsconfigFilePath, buildTsconfig, { space: 2 });
|
|
110
121
|
}
|
|
111
122
|
}
|
|
@@ -2,9 +2,10 @@ import ts from "typescript";
|
|
|
2
2
|
import * as os from "os";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import { ISdCliPackageBuildResult } from "../commons";
|
|
5
|
+
import webpack from "webpack";
|
|
5
6
|
|
|
6
7
|
export class SdCliBuildResultUtil {
|
|
7
|
-
public static
|
|
8
|
+
public static convertFromTsDiag(diag: ts.Diagnostic): ISdCliPackageBuildResult | undefined {
|
|
8
9
|
const severity = diag.category === ts.DiagnosticCategory.Error ? "error"
|
|
9
10
|
: diag.category === ts.DiagnosticCategory.Warning ? "warning"
|
|
10
11
|
: undefined;
|
|
@@ -29,6 +30,34 @@ export class SdCliBuildResultUtil {
|
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
public static convertFromWebpackStats(stats: webpack.Stats): ISdCliPackageBuildResult[] {
|
|
34
|
+
const results: ISdCliPackageBuildResult[] = [];
|
|
35
|
+
|
|
36
|
+
for (const statWarn of stats.compilation.warnings) {
|
|
37
|
+
if (stats.compilation.options.ignoreWarnings?.some((ignoreWarning) => ignoreWarning(statWarn, stats.compilation))) continue;
|
|
38
|
+
|
|
39
|
+
results.push(this._convertFromWebpackError("warning", statWarn));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const statErr of stats.compilation.errors) {
|
|
43
|
+
results.push(this._convertFromWebpackError("error", statErr));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return results;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private static _convertFromWebpackError(severity: "warning" | "error", err: webpack.WebpackError): ISdCliPackageBuildResult {
|
|
50
|
+
return {
|
|
51
|
+
filePath: err.file,
|
|
52
|
+
line: err.loc["start"].line,
|
|
53
|
+
char: err.loc["start"].column,
|
|
54
|
+
code: err.name,
|
|
55
|
+
severity,
|
|
56
|
+
message: err.message
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
|
|
32
61
|
public static getMessage(result: ISdCliPackageBuildResult): string {
|
|
33
62
|
let str = "";
|
|
34
63
|
if (result.filePath !== undefined) {
|
|
@@ -4,15 +4,15 @@ import { ObjectUtil } from "@simplysm/sd-core-common";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
|
|
6
6
|
export class SdCliConfigUtil {
|
|
7
|
-
public static
|
|
8
|
-
const confFileCont = FsUtil.
|
|
7
|
+
public static async loadConfigAsync(confFilePath: string, isDev: boolean, opts?: string[]): Promise<ISdCliConfig> {
|
|
8
|
+
const confFileCont = await FsUtil.readJsonAsync(confFilePath);
|
|
9
9
|
let conf = this._getConfigFromFileContent(confFileCont, isDev, opts);
|
|
10
10
|
|
|
11
11
|
// extends
|
|
12
12
|
if (conf.extends) {
|
|
13
13
|
for (const extConfFilePath of conf.extends) {
|
|
14
|
-
const extConf = this.
|
|
15
|
-
conf = this._mergeObj(
|
|
14
|
+
const extConf = await this.loadConfigAsync(path.resolve(path.dirname(confFilePath), extConfFilePath), isDev, opts);
|
|
15
|
+
conf = this._mergeObj(extConf, conf);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
delete conf["extends"];
|