@simplysm/sd-cli 7.0.213 → 7.0.221
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/build-tool/SdCliElectron.mjs +6 -2
- package/dist/builder/SdCliClientBuilder.d.ts +1 -2
- package/dist/builder/SdCliClientBuilder.mjs +32 -65
- package/dist/builder/SdCliServerBuilder.mjs +9 -1
- package/dist/entry-points/SdCliWorkspace.mjs +53 -10
- package/dist/packages/SdCliPackage.d.ts +1 -3
- package/dist/packages/SdCliPackage.mjs +72 -30
- package/dist/worker/build-worker.d.ts +1 -0
- package/dist/worker/build-worker.mjs +67 -0
- package/package.json +7 -10
- package/src/build-tool/SdCliElectron.ts +7 -2
- package/src/builder/SdCliClientBuilder.ts +33 -68
- package/src/builder/SdCliServerBuilder.ts +8 -0
- package/src/entry-points/SdCliWorkspace.ts +59 -9
- package/src/packages/SdCliPackage.ts +85 -34
- package/src/worker/build-worker.ts +74 -0
- package/tsconfig-build.json +2 -1
- package/tsconfig.json +5 -1
|
@@ -16,10 +16,6 @@ import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
|
16
16
|
import { AngularWebpackPlugin } from "@ngtools/webpack";
|
|
17
17
|
import { IndexHtmlWebpackPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/index-html-webpack-plugin";
|
|
18
18
|
import { SassWorkerImplementation } from "@angular-devkit/build-angular/src/sass/sass-service";
|
|
19
|
-
import { HmrLoader } from "@angular-devkit/build-angular/src/webpack/plugins/hmr/hmr-loader";
|
|
20
|
-
import wdm from "webpack-dev-middleware";
|
|
21
|
-
import whm from "webpack-hot-middleware";
|
|
22
|
-
import { NextHandleFunction } from "connect";
|
|
23
19
|
import { LicenseWebpackPlugin } from "license-webpack-plugin";
|
|
24
20
|
import NodePolyfillPlugin from "node-polyfill-webpack-plugin";
|
|
25
21
|
import { createHash } from "crypto";
|
|
@@ -94,7 +90,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
94
90
|
return super.on(event, listener);
|
|
95
91
|
}
|
|
96
92
|
|
|
97
|
-
public async watchAsync(): Promise<
|
|
93
|
+
public async watchAsync(): Promise<void> {
|
|
98
94
|
// DIST 비우기
|
|
99
95
|
await FsUtil.removeAsync(path.resolve(this._rootPath, ".electron"));
|
|
100
96
|
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
@@ -112,7 +108,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
112
108
|
const webpackConfigs = (Object.keys(this._config.builder ?? { web: {} }) as ("web" | "cordova" | "electron")[])
|
|
113
109
|
.map((builderType) => this._getWebpackConfig(true, builderType));
|
|
114
110
|
const multiCompiler = webpack(webpackConfigs);
|
|
115
|
-
|
|
111
|
+
await new Promise<void>((resolve, reject) => {
|
|
116
112
|
multiCompiler.hooks.invalid.tap(this.constructor.name, (fileName) => {
|
|
117
113
|
if (fileName != null) {
|
|
118
114
|
this._logger.debug("파일변경 감지", fileName);
|
|
@@ -132,22 +128,20 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
132
128
|
this._logger.debug("Webpack 빌드 수행...");
|
|
133
129
|
});
|
|
134
130
|
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
multiCompiler.watch({}, async (err, multiStats) => {
|
|
132
|
+
if (err != null || multiStats == null) {
|
|
137
133
|
this.emit("complete", [{
|
|
138
134
|
filePath: undefined,
|
|
139
135
|
line: undefined,
|
|
140
136
|
char: undefined,
|
|
141
137
|
code: undefined,
|
|
142
138
|
severity: "error",
|
|
143
|
-
message: err
|
|
139
|
+
message: err?.stack ?? "알 수 없는 오류 (multiStats=null)"
|
|
144
140
|
}]);
|
|
145
141
|
reject(err);
|
|
146
142
|
return;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
143
|
+
}
|
|
149
144
|
|
|
150
|
-
multiCompiler.hooks.done.tap(this.constructor.name, async (multiStats) => {
|
|
151
145
|
// 결과 반환
|
|
152
146
|
const results = multiStats.stats.mapMany((stats) => SdCliBuildResultUtil.convertFromWebpackStats(stats));
|
|
153
147
|
|
|
@@ -162,23 +156,10 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
162
156
|
|
|
163
157
|
// 마무리
|
|
164
158
|
this._logger.debug("Webpack 빌드 완료");
|
|
165
|
-
resolve(
|
|
159
|
+
resolve();
|
|
166
160
|
|
|
167
161
|
this.emit("complete", results);
|
|
168
162
|
});
|
|
169
|
-
|
|
170
|
-
const middlewares = multiCompiler.compilers.mapMany((compiler) => [
|
|
171
|
-
wdm(compiler, {
|
|
172
|
-
publicPath: compiler.options.output.publicPath,
|
|
173
|
-
index: "index.html",
|
|
174
|
-
stats: false,
|
|
175
|
-
writeToDisk: true
|
|
176
|
-
}),
|
|
177
|
-
whm(compiler, {
|
|
178
|
-
path: `${compiler.options.output.publicPath}__webpack_hmr`,
|
|
179
|
-
log: false
|
|
180
|
-
})
|
|
181
|
-
]);
|
|
182
163
|
});
|
|
183
164
|
}
|
|
184
165
|
|
|
@@ -249,6 +230,8 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
249
230
|
throw new Error("ELECTRON 빌드 패키지의 'dependencies'에는 'dotenv'가 반드시 포함되어야 합니다.");
|
|
250
231
|
}
|
|
251
232
|
|
|
233
|
+
const remoteVersion = npmConfig.dependencies?.["@electron/remote"];
|
|
234
|
+
|
|
252
235
|
const electronSrcPath = path.resolve(this._rootPath, `.electron/src`);
|
|
253
236
|
const electronDistPath = path.resolve(this._rootPath, `.electron/dist`);
|
|
254
237
|
|
|
@@ -263,7 +246,10 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
263
246
|
"electron": electronVersion.replace("^", "")
|
|
264
247
|
},
|
|
265
248
|
dependencies: {
|
|
266
|
-
"dotenv": dotenvVersion
|
|
249
|
+
"dotenv": dotenvVersion,
|
|
250
|
+
...remoteVersion !== undefined ? {
|
|
251
|
+
"@electron/remote": remoteVersion
|
|
252
|
+
} : {}
|
|
267
253
|
}
|
|
268
254
|
});
|
|
269
255
|
|
|
@@ -329,8 +315,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
329
315
|
const internalModuleCachePaths = watch ? this._getInternalModuleCachePaths(workspaceName) : undefined;
|
|
330
316
|
|
|
331
317
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
332
|
-
// const pkgVersion = npmConfig.version;
|
|
333
|
-
// const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
|
|
334
318
|
|
|
335
319
|
const workspacePkgLockContent = FsUtil.readFile(path.resolve(this._workspaceRootPath, "package-lock.json"));
|
|
336
320
|
|
|
@@ -338,7 +322,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
338
322
|
const publicPath = builderType === "web" ? `/${pkgKey}/` : watch ? `/${pkgKey}/${builderType}/` : ``;
|
|
339
323
|
|
|
340
324
|
const cacheBasePath = path.resolve(this._rootPath, ".cache");
|
|
341
|
-
// const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
342
325
|
|
|
343
326
|
const distPath = (builderType === "cordova" && !watch) ? path.resolve(this._cordova!.cordovaPath, "www")
|
|
344
327
|
: (builderType === "electron" && !watch) ? path.resolve(this._rootPath, ".electron/src")
|
|
@@ -351,10 +334,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
351
334
|
const polyfillsFilePath = path.resolve(this._rootPath, "src/polyfills.ts");
|
|
352
335
|
const stylesFilePath = path.resolve(this._rootPath, "src/styles.scss");
|
|
353
336
|
|
|
354
|
-
const hotMiddlewareScripts = watch ? [
|
|
355
|
-
`webpack-hot-middleware/client?path=${publicPath}__webpack_hmr&timeout=20000&reload=true`
|
|
356
|
-
] : [];
|
|
357
|
-
|
|
358
337
|
let prevProgressMessage = "";
|
|
359
338
|
return {
|
|
360
339
|
mode: watch ? "development" : "production",
|
|
@@ -363,7 +342,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
363
342
|
profile: false,
|
|
364
343
|
resolve: {
|
|
365
344
|
roots: [this._rootPath],
|
|
366
|
-
extensions: [".ts", ".tsx", ".mjs", ".cjs", ".js"],
|
|
345
|
+
extensions: [".ts", ".tsx", ".mjs", ".cjs", ".js", ".jsx"],
|
|
367
346
|
symlinks: true,
|
|
368
347
|
modules: [this._workspaceRootPath, "node_modules"],
|
|
369
348
|
mainFields: ["es2015", "browser", "module", "main"],
|
|
@@ -374,9 +353,9 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
374
353
|
},
|
|
375
354
|
context: this._workspaceRootPath,
|
|
376
355
|
entry: {
|
|
377
|
-
main: [
|
|
378
|
-
...FsUtil.exists(polyfillsFilePath) ? { polyfills: [
|
|
379
|
-
...FsUtil.exists(stylesFilePath) ? { styles: [
|
|
356
|
+
main: [mainFilePath],
|
|
357
|
+
...FsUtil.exists(polyfillsFilePath) ? { polyfills: [polyfillsFilePath] } : {},
|
|
358
|
+
...FsUtil.exists(stylesFilePath) ? { styles: [stylesFilePath] } : {}
|
|
380
359
|
},
|
|
381
360
|
output: {
|
|
382
361
|
uniqueName: pkgKey,
|
|
@@ -417,7 +396,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
417
396
|
.update(watch.toString())
|
|
418
397
|
.digest("hex")
|
|
419
398
|
},
|
|
420
|
-
// cache: { type: "memory", maxGenerations: 1 },
|
|
421
399
|
...watch ? {
|
|
422
400
|
snapshot: {
|
|
423
401
|
immutablePaths: internalModuleCachePaths,
|
|
@@ -490,27 +468,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
490
468
|
test: /[/\\]rxjs[/\\]add[/\\].+\.js$/,
|
|
491
469
|
sideEffects: true
|
|
492
470
|
},
|
|
493
|
-
...watch ? [
|
|
494
|
-
{
|
|
495
|
-
loader: HmrLoader,
|
|
496
|
-
include: [mainFilePath]
|
|
497
|
-
}
|
|
498
|
-
] : [],
|
|
499
|
-
...watch ? [
|
|
500
|
-
{
|
|
501
|
-
test: /\.[cm]?jsx?$/,
|
|
502
|
-
enforce: "pre" as const,
|
|
503
|
-
loader: "source-map-loader",
|
|
504
|
-
options: {
|
|
505
|
-
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
506
|
-
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
507
|
-
return !resourcePath.includes("node_modules")
|
|
508
|
-
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
509
|
-
|| workspaceRegex.test(resourcePath);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
] : [],
|
|
514
471
|
{
|
|
515
472
|
test: /\.[cm]?[tj]sx?$/,
|
|
516
473
|
resolve: { fullySpecified: false },
|
|
@@ -528,10 +485,25 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
528
485
|
}
|
|
529
486
|
]
|
|
530
487
|
},
|
|
488
|
+
...watch ? [
|
|
489
|
+
{
|
|
490
|
+
test: /\.[cm]?jsx?$/,
|
|
491
|
+
enforce: "pre" as const,
|
|
492
|
+
loader: "source-map-loader",
|
|
493
|
+
options: {
|
|
494
|
+
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
495
|
+
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
496
|
+
return !resourcePath.includes("node_modules")
|
|
497
|
+
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
498
|
+
|| workspaceRegex.test(resourcePath);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
] : [],
|
|
531
503
|
{
|
|
532
504
|
test: /\.[cm]?tsx?$/,
|
|
533
505
|
loader: "@ngtools/webpack",
|
|
534
|
-
exclude: [/[/\\](?:css-loader|mini-css-extract-plugin|webpack
|
|
506
|
+
exclude: [/[/\\](?:css-loader|mini-css-extract-plugin|webpack)[/\\]/]
|
|
535
507
|
},
|
|
536
508
|
{
|
|
537
509
|
test: /\.css$/i,
|
|
@@ -684,9 +656,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
684
656
|
emitNgModuleScope: watch,
|
|
685
657
|
inlineStyleFileExtension: "scss"
|
|
686
658
|
}),
|
|
687
|
-
// new AnyComponentStyleBudgetChecker(watch ? [] : [
|
|
688
|
-
// { type: Type.AnyComponentStyle, maximumWarning: "2kb", maximumError: "4kb" }
|
|
689
|
-
// ]),
|
|
690
659
|
{
|
|
691
660
|
apply: (compiler: webpack.Compiler) => {
|
|
692
661
|
compiler.hooks.shutdown.tap("sass-worker", () => {
|
|
@@ -696,7 +665,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
696
665
|
},
|
|
697
666
|
new MiniCssExtractPlugin({ filename: "[name].css" }),
|
|
698
667
|
new SuppressExtractedTextChunksWebpackPlugin(),
|
|
699
|
-
// NgBuildAnalyticsPlugin,
|
|
700
668
|
new IndexHtmlWebpackPlugin({
|
|
701
669
|
indexPath: path.resolve(this._rootPath, "src/index.html"),
|
|
702
670
|
outputPath: "index.html",
|
|
@@ -724,9 +692,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
724
692
|
crossOrigin: "none",
|
|
725
693
|
lang: undefined
|
|
726
694
|
}),
|
|
727
|
-
...watch ? [
|
|
728
|
-
new webpack.HotModuleReplacementPlugin()
|
|
729
|
-
] : [],
|
|
730
695
|
new webpack.EnvironmentPlugin({
|
|
731
696
|
SD_VERSION: this._getNpmConfig(this._rootPath)!.version,
|
|
732
697
|
...this._config.env
|
|
@@ -58,6 +58,14 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
58
58
|
|
|
59
59
|
compiler.watch({}, async (err, stats) => {
|
|
60
60
|
if (err != null || stats == null) {
|
|
61
|
+
this.emit("complete", [{
|
|
62
|
+
filePath: undefined,
|
|
63
|
+
line: undefined,
|
|
64
|
+
char: undefined,
|
|
65
|
+
code: undefined,
|
|
66
|
+
severity: "error",
|
|
67
|
+
message: err?.stack ?? "알 수 없는 오류 (stats=null)"
|
|
68
|
+
}]);
|
|
61
69
|
reject(err);
|
|
62
70
|
return;
|
|
63
71
|
}
|
|
@@ -9,6 +9,8 @@ import semver from "semver/preload";
|
|
|
9
9
|
import { SdCliConfigUtil } from "../utils/SdCliConfigUtil";
|
|
10
10
|
import { SdServiceServer } from "@simplysm/sd-service-server";
|
|
11
11
|
import { SdCliLocalUpdate } from "./SdCliLocalUpdate";
|
|
12
|
+
import url from "url";
|
|
13
|
+
import mime from "mime";
|
|
12
14
|
import { NextHandleFunction } from "connect";
|
|
13
15
|
|
|
14
16
|
export class SdCliWorkspace {
|
|
@@ -36,6 +38,7 @@ export class SdCliWorkspace {
|
|
|
36
38
|
|
|
37
39
|
this._logger.debug("패키지 이벤트 설정...");
|
|
38
40
|
let changeCount = 0;
|
|
41
|
+
let changePkgs: SdCliPackage[] = [];
|
|
39
42
|
const totalResultMap = new Map<string, ISdCliPackageBuildResult[]>();
|
|
40
43
|
for (const pkg of pkgs) {
|
|
41
44
|
pkg
|
|
@@ -46,17 +49,35 @@ export class SdCliWorkspace {
|
|
|
46
49
|
changeCount++;
|
|
47
50
|
this._logger.debug(`[${pkg.name}] 빌드를 시작합니다...`);
|
|
48
51
|
})
|
|
49
|
-
.on("complete",
|
|
50
|
-
|
|
51
|
-
await this._restartServerAsync(pkg);
|
|
52
|
-
}
|
|
52
|
+
.on("complete", (results) => {
|
|
53
|
+
changePkgs.push(pkg);
|
|
53
54
|
|
|
54
55
|
this._logger.debug(`[${pkg.name}] 빌드가 완료되었습니다.`);
|
|
55
56
|
totalResultMap.set(pkg.name, results);
|
|
56
57
|
|
|
57
|
-
setTimeout(() => {
|
|
58
|
+
setTimeout(async () => {
|
|
58
59
|
changeCount--;
|
|
59
60
|
if (changeCount === 0) {
|
|
61
|
+
const currChangePkgs = [...changePkgs];
|
|
62
|
+
changePkgs = [];
|
|
63
|
+
|
|
64
|
+
for (const changePkg of currChangePkgs) {
|
|
65
|
+
if (changePkg.config.type === "server" && !results.some((item) => item.severity === "error")) {
|
|
66
|
+
await this._restartServerAsync(changePkg);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (changePkg.config.type === "client") {
|
|
70
|
+
if (typeof changePkg.config.server === "string") {
|
|
71
|
+
const serverInfo = this._serverInfoMap.get(changePkg.config.server);
|
|
72
|
+
serverInfo?.server?.broadcastReload();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const serverInfo = this._serverInfoMap.get("PORT:" + changePkg.config.server.port);
|
|
76
|
+
serverInfo?.server?.broadcastReload();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
60
81
|
this._loggingResults(totalResultMap);
|
|
61
82
|
this._loggingOpenClientHrefs();
|
|
62
83
|
this._logger.info("모든 빌드가 완료되었습니다.");
|
|
@@ -77,11 +98,37 @@ export class SdCliWorkspace {
|
|
|
77
98
|
await pkgs.parallelAsync(async (pkg) => {
|
|
78
99
|
await Wait.until(() => !pkg.allDependencies.some((dep) => pkgNames.includes(dep) && !buildCompletedPackageNames.includes(dep)));
|
|
79
100
|
if (pkg.config.type === "client") {
|
|
80
|
-
|
|
101
|
+
await pkg.watchAsync();
|
|
102
|
+
|
|
103
|
+
const pkgMiddleware: NextHandleFunction = (req, res, next) => {
|
|
104
|
+
if (req.method === "GET") {
|
|
105
|
+
const urlObj = url.parse(req.url!, true, false);
|
|
106
|
+
const urlPathChain = decodeURI(urlObj.pathname!.slice(1)).split("/");
|
|
107
|
+
if (urlPathChain[0] === pkg.name.split("/").last()!) {
|
|
108
|
+
let targetFilePath = path.resolve(pkg.rootPath, "dist", ...urlPathChain.slice(1));
|
|
109
|
+
targetFilePath = FsUtil.exists(targetFilePath) && FsUtil.stat(targetFilePath).isDirectory() ? path.resolve(targetFilePath, "index.html") : targetFilePath;
|
|
110
|
+
|
|
111
|
+
if (FsUtil.exists(targetFilePath) && !path.basename(targetFilePath).startsWith(".")) {
|
|
112
|
+
const fileStream = FsUtil.createReadStream(targetFilePath);
|
|
113
|
+
const targetFileSize = FsUtil.lstat(targetFilePath).size;
|
|
114
|
+
|
|
115
|
+
fileStream.on("open", () => {
|
|
116
|
+
res.setHeader("Content-Length", targetFileSize);
|
|
117
|
+
res.setHeader("Content-Type", mime.getType(targetFilePath)!);
|
|
118
|
+
res.writeHead(200);
|
|
119
|
+
});
|
|
120
|
+
fileStream.pipe(res);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
next();
|
|
127
|
+
};
|
|
81
128
|
|
|
82
129
|
if (typeof pkg.config.server === "string") {
|
|
83
130
|
const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { middlewares: [], clientInfos: [] });
|
|
84
|
-
serverInfo.middlewares.push(
|
|
131
|
+
serverInfo.middlewares.push(pkgMiddleware);
|
|
85
132
|
serverInfo.clientInfos.push({
|
|
86
133
|
pkgKey: pkg.name.split("/").last()!,
|
|
87
134
|
platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
|
|
@@ -89,7 +136,10 @@ export class SdCliWorkspace {
|
|
|
89
136
|
});
|
|
90
137
|
}
|
|
91
138
|
else { // DEV SERVER
|
|
92
|
-
const serverInfo = this._serverInfoMap.getOrCreate("
|
|
139
|
+
const serverInfo = this._serverInfoMap.getOrCreate("PORT:" + pkg.config.server.port, {
|
|
140
|
+
middlewares: [],
|
|
141
|
+
clientInfos: []
|
|
142
|
+
});
|
|
93
143
|
if (serverInfo.server === undefined) {
|
|
94
144
|
const server = new SdServiceServer({
|
|
95
145
|
rootPath: process.cwd(),
|
|
@@ -98,7 +148,7 @@ export class SdCliWorkspace {
|
|
|
98
148
|
});
|
|
99
149
|
await server.listenAsync();
|
|
100
150
|
serverInfo.server = server;
|
|
101
|
-
serverInfo.server.devMiddlewares =
|
|
151
|
+
serverInfo.server.devMiddlewares = [pkgMiddleware];
|
|
102
152
|
serverInfo.clientInfos.push({
|
|
103
153
|
pkgKey: pkg.name.split("/").last()!,
|
|
104
154
|
platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
|
|
@@ -2,16 +2,13 @@ import { INpmConfig, ISdCliPackageBuildResult, ITsconfig, TSdCliPackageConfig }
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { FsUtil, PathUtil, SdProcess } from "@simplysm/sd-core-node";
|
|
4
4
|
import { EventEmitter } from "events";
|
|
5
|
-
import { NeverEntryError, ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
6
|
-
import { SdCliTsLibBuilder } from "../builder/SdCliTsLibBuilder";
|
|
7
|
-
import { SdCliJsLibBuilder } from "../builder/SdCliJsLibBuilder";
|
|
8
|
-
import { SdCliServerBuilder } from "../builder/SdCliServerBuilder";
|
|
5
|
+
import { JsonConvert, NeverEntryError, ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
9
6
|
import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
|
|
10
|
-
import { SdCliClientBuilder } from "../builder/SdCliClientBuilder";
|
|
11
|
-
import { NextHandleFunction } from "connect";
|
|
12
7
|
import { SdStorage } from "@simplysm/sd-storage";
|
|
13
8
|
import ts from "typescript";
|
|
14
9
|
import { SdCliGithubApi } from "../build-tool/SdCliGithubApi";
|
|
10
|
+
import cp from "child_process";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
15
12
|
|
|
16
13
|
export class SdCliPackage extends EventEmitter {
|
|
17
14
|
private readonly _npmConfig: INpmConfig;
|
|
@@ -70,19 +67,91 @@ export class SdCliPackage extends EventEmitter {
|
|
|
70
67
|
await FsUtil.writeJsonAsync(npmConfigFilePath, this._npmConfig, { space: 2 });
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
public async watchAsync(): Promise<
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
70
|
+
public async watchAsync(): Promise<void> {
|
|
71
|
+
const isTs = FsUtil.exists(path.resolve(this.rootPath, "tsconfig.json"));
|
|
72
|
+
|
|
73
|
+
if (isTs) {
|
|
74
|
+
await this._genBuildTsconfigAsync();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const workerPath = fileURLToPath(await import.meta.resolve!("../worker/build-worker"));
|
|
78
|
+
await new Promise<void>((resolve, reject) => {
|
|
79
|
+
const worker = cp.fork(workerPath, [
|
|
80
|
+
"watch",
|
|
81
|
+
this.rootPath,
|
|
82
|
+
JsonConvert.stringify(this.config),
|
|
83
|
+
this._workspaceRootPath
|
|
84
|
+
], {
|
|
85
|
+
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
86
|
+
env: process.env
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
worker.on("error", (err) => {
|
|
90
|
+
reject(err);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
worker.stdout!.pipe(process.stdout);
|
|
94
|
+
worker.stderr!.pipe(process.stderr);
|
|
95
|
+
|
|
96
|
+
worker.on("message", (json: string) => {
|
|
97
|
+
const msg = JsonConvert.parse(json);
|
|
98
|
+
if (msg.event === "ready") {
|
|
99
|
+
resolve();
|
|
100
|
+
}
|
|
101
|
+
else if (msg.event === "change") {
|
|
102
|
+
this.emit("change");
|
|
103
|
+
}
|
|
104
|
+
else if (msg.event === "complete") {
|
|
105
|
+
this.emit("complete", msg.body);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
throw new NeverEntryError();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
});
|
|
82
112
|
}
|
|
83
113
|
|
|
84
114
|
public async buildAsync(): Promise<ISdCliPackageBuildResult[]> {
|
|
85
|
-
|
|
115
|
+
const isTs = FsUtil.exists(path.resolve(this.rootPath, "tsconfig.json"));
|
|
116
|
+
|
|
117
|
+
if (isTs) {
|
|
118
|
+
await this._genBuildTsconfigAsync();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const workerPath = fileURLToPath(await import.meta.resolve!("../worker/build-worker"));
|
|
122
|
+
return await new Promise<ISdCliPackageBuildResult[]>((resolve, reject) => {
|
|
123
|
+
const worker = cp.fork(workerPath, [
|
|
124
|
+
"build",
|
|
125
|
+
this.rootPath,
|
|
126
|
+
JsonConvert.stringify(this.config),
|
|
127
|
+
this._workspaceRootPath
|
|
128
|
+
], {
|
|
129
|
+
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
130
|
+
env: process.env
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
worker.on("error", (err) => {
|
|
134
|
+
reject(err);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
worker.stdout!.pipe(process.stdout);
|
|
138
|
+
worker.stderr!.pipe(process.stderr);
|
|
139
|
+
|
|
140
|
+
let result: ISdCliPackageBuildResult[] = [];
|
|
141
|
+
|
|
142
|
+
worker.on("message", (json: string) => {
|
|
143
|
+
result = JsonConvert.parse(json);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
worker.on("exit", (code) => {
|
|
147
|
+
if (code !== 0) {
|
|
148
|
+
reject(new Error(`오류와 함께 닫힘 (${code})`));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
resolve(result);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
86
155
|
}
|
|
87
156
|
|
|
88
157
|
public async publishAsync(): Promise<void> {
|
|
@@ -156,24 +225,6 @@ export class SdCliPackage extends EventEmitter {
|
|
|
156
225
|
}
|
|
157
226
|
}
|
|
158
227
|
|
|
159
|
-
private async _createBuilderAsync(): Promise<SdCliJsLibBuilder | SdCliTsLibBuilder | SdCliServerBuilder | SdCliClientBuilder> {
|
|
160
|
-
const isTs = FsUtil.exists(path.resolve(this.rootPath, "tsconfig.json"));
|
|
161
|
-
|
|
162
|
-
if (isTs) {
|
|
163
|
-
await this._genBuildTsconfigAsync();
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (this.config.type === "library") {
|
|
167
|
-
return isTs ? new SdCliTsLibBuilder(this.rootPath, this.config, this._workspaceRootPath) : new SdCliJsLibBuilder(this.rootPath);
|
|
168
|
-
}
|
|
169
|
-
else if (this.config.type === "server") {
|
|
170
|
-
return new SdCliServerBuilder(this.rootPath, this.config, this._workspaceRootPath);
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
return new SdCliClientBuilder(this.rootPath, this.config, this._workspaceRootPath);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
228
|
private async _genBuildTsconfigAsync(): Promise<void> {
|
|
178
229
|
const baseTsconfigFilePath = path.resolve(this.rootPath, "tsconfig.json");
|
|
179
230
|
const baseTsconfig: ITsconfig = await FsUtil.readJsonAsync(baseTsconfigFilePath);
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SdCliTsLibBuilder } from "../builder/SdCliTsLibBuilder";
|
|
2
|
+
import { SdCliJsLibBuilder } from "../builder/SdCliJsLibBuilder";
|
|
3
|
+
import { SdCliServerBuilder } from "../builder/SdCliServerBuilder";
|
|
4
|
+
import { SdCliClientBuilder } from "../builder/SdCliClientBuilder";
|
|
5
|
+
import { FsUtil, Logger, LoggerSeverity } from "@simplysm/sd-core-node";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { JsonConvert } from "@simplysm/sd-core-common";
|
|
8
|
+
import { TSdCliPackageConfig } from "../commons";
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if (process.env["SD_CLI_LOGGER_SEVERITY"] === "DEBUG") {
|
|
12
|
+
Logger.setConfig({
|
|
13
|
+
console: {
|
|
14
|
+
level: LoggerSeverity.debug
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
Logger.setConfig({
|
|
20
|
+
dot: true
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const type = process.argv[2] as ("build" | "watch");
|
|
25
|
+
const rootPath = process.argv[3];
|
|
26
|
+
const config = JsonConvert.parse(process.argv[4]) as TSdCliPackageConfig;
|
|
27
|
+
const workspaceRootPath = process.argv[5];
|
|
28
|
+
|
|
29
|
+
function createBuilder(): SdCliJsLibBuilder | SdCliTsLibBuilder | SdCliServerBuilder | SdCliClientBuilder {
|
|
30
|
+
const isTs = FsUtil.exists(path.resolve(rootPath, "tsconfig.json"));
|
|
31
|
+
|
|
32
|
+
if (config.type === "library") {
|
|
33
|
+
return isTs ? new SdCliTsLibBuilder(rootPath, config, workspaceRootPath) : new SdCliJsLibBuilder(rootPath);
|
|
34
|
+
}
|
|
35
|
+
else if (config.type === "server") {
|
|
36
|
+
return new SdCliServerBuilder(rootPath, config, workspaceRootPath);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
return new SdCliClientBuilder(rootPath, config, workspaceRootPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const builder = createBuilder();
|
|
44
|
+
|
|
45
|
+
if (type === "build") {
|
|
46
|
+
builder.buildAsync()
|
|
47
|
+
.then((result) => {
|
|
48
|
+
process.send!(JsonConvert.stringify(result));
|
|
49
|
+
process.exit(0);
|
|
50
|
+
})
|
|
51
|
+
.catch((err) => {
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
console.error(err);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
builder
|
|
59
|
+
.on("change", () => {
|
|
60
|
+
process.send!(JsonConvert.stringify({ event: "change" }));
|
|
61
|
+
})
|
|
62
|
+
.on("complete", (results) => {
|
|
63
|
+
process.send!(JsonConvert.stringify({ event: "complete", body: results }));
|
|
64
|
+
})
|
|
65
|
+
.watchAsync()
|
|
66
|
+
.then(() => {
|
|
67
|
+
process.send!(JsonConvert.stringify({ event: "ready" }));
|
|
68
|
+
})
|
|
69
|
+
.catch((err) => {
|
|
70
|
+
// eslint-disable-next-line no-console
|
|
71
|
+
console.error(err);
|
|
72
|
+
process.exit(1);
|
|
73
|
+
});
|
|
74
|
+
}
|
package/tsconfig-build.json
CHANGED
package/tsconfig.json
CHANGED
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
"@simplysm/sd-orm-common": [
|
|
23
23
|
"../sd-orm-common/src/index.ts"
|
|
24
24
|
],
|
|
25
|
+
"@simplysm/sd-orm-node": [
|
|
26
|
+
"../sd-orm-node/src/index.ts"
|
|
27
|
+
],
|
|
25
28
|
"@simplysm/sd-storage": [
|
|
26
29
|
"../sd-storage/src/index.ts"
|
|
27
30
|
]
|
|
@@ -29,6 +32,7 @@
|
|
|
29
32
|
},
|
|
30
33
|
"files": [
|
|
31
34
|
"src/bin/sd-cli.ts",
|
|
32
|
-
"src/index.ts"
|
|
35
|
+
"src/index.ts",
|
|
36
|
+
"src/worker/build-worker.ts"
|
|
33
37
|
]
|
|
34
38
|
}
|