@simplysm/sd-cli 7.0.75 → 7.0.77
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/.eslintrc.cjs +3 -0
- package/dist/bin/sd-cli.mjs +38 -3
- package/dist/build-tool/SdCliCordova.mjs +26 -18
- package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +1 -0
- package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +11 -4
- package/dist/build-tool/SdCliPackageLinter.mjs +9 -5
- package/dist/builder/SdCliClientBuilder.d.ts +1 -0
- package/dist/builder/SdCliClientBuilder.mjs +44 -37
- package/dist/builder/SdCliJsLibBuilder.mjs +3 -3
- package/dist/builder/SdCliServerBuilder.d.ts +0 -1
- package/dist/builder/SdCliServerBuilder.mjs +13 -39
- package/dist/builder/SdCliTsLibBuilder.d.ts +1 -0
- package/dist/builder/SdCliTsLibBuilder.mjs +18 -6
- package/dist/commons.d.ts +2 -4
- package/dist/entry-points/SdCliFileCrypto.d.ts +7 -0
- package/dist/entry-points/SdCliFileCrypto.mjs +72 -0
- package/dist/entry-points/SdCliLocalUpdate.mjs +3 -3
- package/dist/entry-points/SdCliPrepare.mjs +1 -1
- package/dist/entry-points/SdCliWorkspace.mjs +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +2 -1
- package/dist/ng-tools/SdCliNgModuleGenerator.mjs +1 -4
- package/dist/ng-tools/babel/SdCliBbFileMetadata.d.ts +1 -1
- package/dist/ng-tools/babel/SdCliBbFileMetadata.mjs +4 -4
- package/dist/ng-tools/babel/TSdCliBbNgMetadata.mjs +6 -6
- package/dist/utils/SdCliBuildResultUtil.mjs +4 -1
- package/package.json +6 -6
- package/src/bin/sd-cli.ts +53 -3
- package/src/build-tool/SdCliCordova.ts +29 -17
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +19 -11
- package/src/build-tool/SdCliPackageLinter.ts +8 -4
- package/src/builder/SdCliClientBuilder.ts +41 -32
- package/src/builder/SdCliJsLibBuilder.ts +2 -2
- package/src/builder/SdCliServerBuilder.ts +9 -36
- package/src/builder/SdCliTsLibBuilder.ts +21 -5
- package/src/commons.ts +2 -2
- package/src/entry-points/SdCliFileCrypto.ts +87 -0
- package/src/entry-points/SdCliLocalUpdate.ts +2 -2
- package/src/entry-points/SdCliPrepare.ts +1 -1
- package/src/entry-points/SdCliWorkspace.ts +1 -1
- package/src/index.ts +1 -0
- package/src/ng-tools/SdCliNgModuleGenerator.ts +1 -4
- package/src/ng-tools/babel/SdCliBbFileMetadata.ts +5 -5
- package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +5 -5
- package/src/utils/SdCliBuildResultUtil.ts +4 -0
|
@@ -7,7 +7,6 @@ import ts from "typescript";
|
|
|
7
7
|
import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
|
|
8
8
|
import { NamedChunksPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/named-chunks-plugin";
|
|
9
9
|
import {
|
|
10
|
-
AnyComponentStyleBudgetChecker,
|
|
11
10
|
CommonJsUsageWarnPlugin,
|
|
12
11
|
DedupeModuleResolvePlugin,
|
|
13
12
|
JavaScriptOptimizerPlugin,
|
|
@@ -23,7 +22,6 @@ import wdm from "webpack-dev-middleware";
|
|
|
23
22
|
import whm from "webpack-hot-middleware";
|
|
24
23
|
import { NextHandleFunction } from "connect";
|
|
25
24
|
import { LicenseWebpackPlugin } from "license-webpack-plugin";
|
|
26
|
-
import { Type } from "@angular-devkit/build-angular";
|
|
27
25
|
import NodePolyfillPlugin from "node-polyfill-webpack-plugin";
|
|
28
26
|
import { createHash } from "crypto";
|
|
29
27
|
import ESLintWebpackPlugin from "eslint-webpack-plugin";
|
|
@@ -36,6 +34,7 @@ import { augmentAppWithServiceWorker } from "@angular-devkit/build-angular/src/u
|
|
|
36
34
|
import { StringUtil } from "@simplysm/sd-core-common";
|
|
37
35
|
import { SdCliNgModuleGenerator } from "../ng-tools/SdCliNgModuleGenerator";
|
|
38
36
|
import { SdCliCordova } from "../build-tool/SdCliCordova";
|
|
37
|
+
import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
|
|
39
38
|
import LintResult = ESLint.LintResult;
|
|
40
39
|
|
|
41
40
|
export class SdCliClientBuilder extends EventEmitter {
|
|
@@ -48,6 +47,8 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
48
47
|
|
|
49
48
|
private readonly _cordova?: SdCliCordova;
|
|
50
49
|
|
|
50
|
+
private readonly _hasAngularRoute: boolean;
|
|
51
|
+
|
|
51
52
|
public constructor(private readonly _rootPath: string,
|
|
52
53
|
private readonly _config: ISdCliClientPackageConfig,
|
|
53
54
|
private readonly _workspaceRootPath: string) {
|
|
@@ -61,6 +62,9 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
61
62
|
const tsconfig = FsUtil.readJson(this._tsconfigFilePath) as ITsconfig;
|
|
62
63
|
this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath, tsconfig.angularCompilerOptions);
|
|
63
64
|
|
|
65
|
+
// isAngular
|
|
66
|
+
this._hasAngularRoute = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/router");
|
|
67
|
+
|
|
64
68
|
// NgModule 생성기 초기화
|
|
65
69
|
this._ngModuleGenerator = new SdCliNgModuleGenerator(this._rootPath, [
|
|
66
70
|
"controls",
|
|
@@ -73,11 +77,11 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
73
77
|
"print-templates",
|
|
74
78
|
"toasts",
|
|
75
79
|
"AppPage"
|
|
76
|
-
], {
|
|
80
|
+
], this._hasAngularRoute ? {
|
|
77
81
|
glob: "**/*Page.ts",
|
|
78
82
|
fileEndsWith: "Page",
|
|
79
83
|
rootClassName: "AppPage"
|
|
80
|
-
});
|
|
84
|
+
} : undefined);
|
|
81
85
|
|
|
82
86
|
// CORDOVA
|
|
83
87
|
if (this._config.cordova) {
|
|
@@ -244,7 +248,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
244
248
|
const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
|
|
245
249
|
|
|
246
250
|
const pkgKey = npmConfig.name.split("/").last()!;
|
|
247
|
-
const publicPath = `/${pkgKey}/`;
|
|
251
|
+
const publicPath = (this._cordova && !watch) ? `/` : `/${pkgKey}/`;
|
|
248
252
|
|
|
249
253
|
const cacheBasePath = path.resolve(this._rootPath, ".cache");
|
|
250
254
|
const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
@@ -257,6 +261,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
257
261
|
const polyfillsFilePath = path.resolve(this._rootPath, "src/polyfills.ts");
|
|
258
262
|
const stylesFilePath = path.resolve(this._rootPath, "src/styles.scss");
|
|
259
263
|
|
|
264
|
+
let prevProgressMessage = "";
|
|
260
265
|
return {
|
|
261
266
|
mode: watch ? "development" : "production",
|
|
262
267
|
devtool: false,
|
|
@@ -396,6 +401,27 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
396
401
|
test: /[/\\]rxjs[/\\]add[/\\].+\.js$/,
|
|
397
402
|
sideEffects: true
|
|
398
403
|
},
|
|
404
|
+
...watch ? [
|
|
405
|
+
{
|
|
406
|
+
loader: HmrLoader,
|
|
407
|
+
include: [mainFilePath]
|
|
408
|
+
}
|
|
409
|
+
] : [],
|
|
410
|
+
...watch ? [
|
|
411
|
+
{
|
|
412
|
+
test: /\.[cm]?jsx?$/,
|
|
413
|
+
enforce: "pre" as const,
|
|
414
|
+
loader: "source-map-loader",
|
|
415
|
+
options: {
|
|
416
|
+
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
417
|
+
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
418
|
+
return !resourcePath.includes("node_modules")
|
|
419
|
+
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
420
|
+
|| workspaceRegex.test(resourcePath);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
] : [],
|
|
399
425
|
{
|
|
400
426
|
test: /\.[cm]?[tj]sx?$/,
|
|
401
427
|
resolve: { fullySpecified: false },
|
|
@@ -413,21 +439,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
413
439
|
}
|
|
414
440
|
]
|
|
415
441
|
},
|
|
416
|
-
...watch ? [
|
|
417
|
-
{
|
|
418
|
-
test: /\.[cm]?jsx?$/,
|
|
419
|
-
enforce: "pre" as const,
|
|
420
|
-
loader: "source-map-loader",
|
|
421
|
-
options: {
|
|
422
|
-
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
423
|
-
const workspaceRegex = new RegExp(`node_modules[\\\\/]@${workspaceName}[\\\\/]`);
|
|
424
|
-
return !resourcePath.includes("node_modules")
|
|
425
|
-
|| (/node_modules[\\/]@simplysm[\\/]/).test(resourcePath)
|
|
426
|
-
|| workspaceRegex.test(resourcePath);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
] : [],
|
|
431
442
|
{
|
|
432
443
|
test: /\.[cm]?tsx?$/,
|
|
433
444
|
loader: "@ngtools/webpack",
|
|
@@ -486,12 +497,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
486
497
|
}
|
|
487
498
|
]
|
|
488
499
|
},
|
|
489
|
-
...watch ? [
|
|
490
|
-
{
|
|
491
|
-
loader: HmrLoader,
|
|
492
|
-
include: [mainFilePath]
|
|
493
|
-
}
|
|
494
|
-
] : [],
|
|
495
500
|
{
|
|
496
501
|
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico|otf|xlsx?|pptx?|docx?|zip|pfx|pkl)$/,
|
|
497
502
|
type: "asset/resource"
|
|
@@ -502,13 +507,17 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
502
507
|
new NodePolyfillPlugin(),
|
|
503
508
|
new NamedChunksPlugin(),
|
|
504
509
|
new DedupeModuleResolvePlugin(),
|
|
505
|
-
|
|
510
|
+
new webpack.ProgressPlugin({
|
|
506
511
|
handler: (per: number, msg: string, ...args: string[]) => {
|
|
507
512
|
const phaseText = msg ? ` - phase: ${msg}` : "";
|
|
508
513
|
const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
|
|
509
|
-
|
|
514
|
+
const progressMessage = `Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`;
|
|
515
|
+
if (progressMessage !== prevProgressMessage) {
|
|
516
|
+
prevProgressMessage = progressMessage;
|
|
517
|
+
this._logger.debug(progressMessage);
|
|
518
|
+
}
|
|
510
519
|
}
|
|
511
|
-
})
|
|
520
|
+
}),
|
|
512
521
|
new CommonJsUsageWarnPlugin(),
|
|
513
522
|
...watch ? [] : [
|
|
514
523
|
new LicenseWebpackPlugin({
|
|
@@ -565,9 +574,9 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
565
574
|
emitNgModuleScope: watch,
|
|
566
575
|
inlineStyleFileExtension: "scss"
|
|
567
576
|
}),
|
|
568
|
-
new AnyComponentStyleBudgetChecker(watch ? [] : [
|
|
569
|
-
|
|
570
|
-
]),
|
|
577
|
+
// new AnyComponentStyleBudgetChecker(watch ? [] : [
|
|
578
|
+
// { type: Type.AnyComponentStyle, maximumWarning: "2kb", maximumError: "4kb" }
|
|
579
|
+
// ]),
|
|
571
580
|
{
|
|
572
581
|
apply: (compiler: webpack.Compiler) => {
|
|
573
582
|
compiler.hooks.shutdown.tap("sass-worker", () => {
|
|
@@ -29,7 +29,7 @@ export class SdCliJsLibBuilder extends EventEmitter {
|
|
|
29
29
|
const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
30
30
|
if (changeFilePaths.length === 0) return;
|
|
31
31
|
|
|
32
|
-
this._logger.debug("파일 변경 감지"
|
|
32
|
+
this._logger.debug("파일 변경 감지");
|
|
33
33
|
this.emit("change");
|
|
34
34
|
const watchBuildResults: ISdCliPackageBuildResult[] = [];
|
|
35
35
|
|
|
@@ -56,7 +56,7 @@ export class SdCliJsLibBuilder extends EventEmitter {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
private async getRelatedPathsAsync(): Promise<string[]> {
|
|
59
|
-
const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs
|
|
59
|
+
const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs)");
|
|
60
60
|
const mySourceFilePaths = await FsUtil.globAsync(mySourceGlobPath, {
|
|
61
61
|
ignore: [
|
|
62
62
|
"**/node_modules/**",
|
|
@@ -102,9 +102,6 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
102
102
|
// pm2.json 파일 쓰기
|
|
103
103
|
await this._writeDistPm2ConfigFileAsync();
|
|
104
104
|
|
|
105
|
-
// iis 파일 쓰기
|
|
106
|
-
await this._writeDistIisConfigFileAsync();
|
|
107
|
-
|
|
108
105
|
// 배포용 package.json 파일 생성
|
|
109
106
|
await this._writeDistNpmConfigFileAsync(extModules.filter((item) => item.exists).map((item) => item.name));
|
|
110
107
|
|
|
@@ -155,36 +152,6 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
155
152
|
);
|
|
156
153
|
}
|
|
157
154
|
|
|
158
|
-
private async _writeDistIisConfigFileAsync(): Promise<void> {
|
|
159
|
-
if (this._config.iis === undefined || this._config.iis === false) return;
|
|
160
|
-
|
|
161
|
-
const iisDistPath = path.resolve(this._parsedTsconfig.options.outDir!, "web.config");
|
|
162
|
-
const serverExeFilePath = (this._config.iis !== true && "serverExeFilePath" in this._config.iis)
|
|
163
|
-
? (this._config.iis.serverExeFilePath ?? "C:\\Program Files\\nodejs\\node.exe")
|
|
164
|
-
: "C:\\Program Files\\nodejs\\node.exe";
|
|
165
|
-
await FsUtil.writeFileAsync(iisDistPath, `
|
|
166
|
-
<configuration>
|
|
167
|
-
<system.webServer>
|
|
168
|
-
<webSocket enabled="false" />
|
|
169
|
-
<handlers>
|
|
170
|
-
<add name="iisnode" path="main.js" verb="*" modules="iisnode" />
|
|
171
|
-
</handlers>
|
|
172
|
-
<iisnode nodeProcessCommandLine="${serverExeFilePath}"
|
|
173
|
-
watchedFiles="web.config;*.js"
|
|
174
|
-
loggingEnabled="true"
|
|
175
|
-
devErrorsEnabled="true" />
|
|
176
|
-
<rewrite>
|
|
177
|
-
<rules>
|
|
178
|
-
<rule name="main">
|
|
179
|
-
<action type="Rewrite" url="main.mjs" />
|
|
180
|
-
</rule>
|
|
181
|
-
</rules>
|
|
182
|
-
</rewrite>
|
|
183
|
-
<httpErrors errorMode="Detailed" />
|
|
184
|
-
</system.webServer>
|
|
185
|
-
</configuration>`.trim());
|
|
186
|
-
}
|
|
187
|
-
|
|
188
155
|
private async _writeDistNpmConfigFileAsync(deps: string[]): Promise<void> {
|
|
189
156
|
const distNpmConfig = ObjectUtil.clone(this._getNpmConfig(this._rootPath))!;
|
|
190
157
|
distNpmConfig.dependencies = {};
|
|
@@ -225,6 +192,8 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
225
192
|
const cacheBasePath = path.resolve(this._rootPath, ".cache");
|
|
226
193
|
const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
227
194
|
|
|
195
|
+
|
|
196
|
+
let prevProgressMessage = "";
|
|
228
197
|
return {
|
|
229
198
|
mode: watch ? "development" : "production",
|
|
230
199
|
devtool: false,
|
|
@@ -425,14 +394,18 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
425
394
|
}
|
|
426
395
|
return resultMessages.join(os.EOL);
|
|
427
396
|
}
|
|
428
|
-
})
|
|
397
|
+
}),
|
|
429
398
|
new webpack.ProgressPlugin({
|
|
430
399
|
handler: (per: number, msg: string, ...args: string[]) => {
|
|
431
400
|
const phaseText = msg ? ` - phase: ${msg}` : "";
|
|
432
401
|
const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
|
|
433
|
-
|
|
402
|
+
const progressMessage = `Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`;
|
|
403
|
+
if (progressMessage !== prevProgressMessage) {
|
|
404
|
+
prevProgressMessage = progressMessage;
|
|
405
|
+
this._logger.debug(progressMessage);
|
|
406
|
+
}
|
|
434
407
|
}
|
|
435
|
-
})
|
|
408
|
+
})
|
|
436
409
|
]
|
|
437
410
|
};
|
|
438
411
|
}
|
|
@@ -37,6 +37,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
37
37
|
private readonly _npmConfigMap = new Map<string, INpmConfig>();
|
|
38
38
|
|
|
39
39
|
private readonly _isAngular: boolean;
|
|
40
|
+
private readonly _hasAngularRoute: boolean;
|
|
40
41
|
|
|
41
42
|
public constructor(private readonly _rootPath: string,
|
|
42
43
|
private readonly _config: ISdCliLibPackageConfig,
|
|
@@ -52,6 +53,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
52
53
|
|
|
53
54
|
// isAngular
|
|
54
55
|
this._isAngular = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/core");
|
|
56
|
+
this._hasAngularRoute = SdCliNpmConfigUtil.getDependencies(npmConfig).defaults.includes("@angular/router");
|
|
55
57
|
|
|
56
58
|
// tsconfig
|
|
57
59
|
this._tsconfigFilePath = path.resolve(this._rootPath, "tsconfig-build.json");
|
|
@@ -71,11 +73,11 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
71
73
|
"print-templates",
|
|
72
74
|
"toasts",
|
|
73
75
|
"AppPage"
|
|
74
|
-
], {
|
|
76
|
+
], this._hasAngularRoute ? {
|
|
75
77
|
glob: "**/*Page.ts",
|
|
76
78
|
fileEndsWith: "Page",
|
|
77
79
|
rootClassName: "AppPage"
|
|
78
|
-
});
|
|
80
|
+
} : undefined);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
// index 생성기 초기화
|
|
@@ -117,12 +119,21 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
117
119
|
const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
118
120
|
if (changeFilePaths.length === 0) return;
|
|
119
121
|
|
|
120
|
-
this._logger.debug("파일 변경 감지",
|
|
122
|
+
this._logger.debug("파일 변경 감지", changeFilePaths);
|
|
121
123
|
this.emit("change");
|
|
122
124
|
|
|
123
125
|
this._logger.debug("변경된 파일의 캐쉬 삭제...");
|
|
124
126
|
for (const changeFilePath of changeFilePaths) {
|
|
125
|
-
this._fileCache.
|
|
127
|
+
const fileCache = this._fileCache.get(PathUtil.posix(changeFilePath));
|
|
128
|
+
if (fileCache) {
|
|
129
|
+
if (fileCache.importerSet) {
|
|
130
|
+
for (const importer of fileCache.importerSet.values()) {
|
|
131
|
+
this._fileCache.delete(importer);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this._fileCache.delete(PathUtil.posix(changeFilePath));
|
|
136
|
+
}
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
if (this._ngModuleGenerator) {
|
|
@@ -161,6 +172,10 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
161
172
|
this._logger.debug("린트...");
|
|
162
173
|
buildResults.push(...await this._linter.lintAsync(relatedPaths, buildPack.program));
|
|
163
174
|
|
|
175
|
+
this._logger.debug("변경감지 대상목록 재구성...");
|
|
176
|
+
const watchRelatedPaths = await this.getAllRelatedPathsAsync();
|
|
177
|
+
watcher.add(watchRelatedPaths);
|
|
178
|
+
|
|
164
179
|
this.emit("complete", buildResults);
|
|
165
180
|
}
|
|
166
181
|
|
|
@@ -202,7 +217,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
202
217
|
|| (/node_modules[\\/]@simplysm[\\/]/).test(filePath)
|
|
203
218
|
|| workspaceRegex.test(filePath);
|
|
204
219
|
});
|
|
205
|
-
const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs|*.ts)");
|
|
220
|
+
const mySourceGlobPath = path.resolve(this._rootPath, "**", "+(*.js|*.cjs|*.mjs|*.ts|*.scss)");
|
|
206
221
|
const mySourceFilePaths = await FsUtil.globAsync(mySourceGlobPath, {
|
|
207
222
|
ignore: [
|
|
208
223
|
"**/node_modules/**",
|
|
@@ -419,6 +434,7 @@ interface IFileCache {
|
|
|
419
434
|
sourceFile?: ts.SourceFile;
|
|
420
435
|
content?: string;
|
|
421
436
|
styleContent?: string;
|
|
437
|
+
importerSet?: Set<string>;
|
|
422
438
|
}
|
|
423
439
|
|
|
424
440
|
interface ISdBuildPack {
|
package/src/commons.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface INpmConfig {
|
|
2
2
|
name: string;
|
|
3
3
|
version: string;
|
|
4
|
+
type?: "module";
|
|
4
5
|
workspaces?: string[];
|
|
5
6
|
main?: string;
|
|
6
7
|
types?: string;
|
|
@@ -56,7 +57,6 @@ export interface ISdCliServerPackageConfig {
|
|
|
56
57
|
env?: Record<string, string>;
|
|
57
58
|
configs?: Record<string, any>;
|
|
58
59
|
pm2?: Record<string, any> | boolean;
|
|
59
|
-
iis?: { serverExeFilePath?: string } | boolean;
|
|
60
60
|
externalNodeModules?: string[];
|
|
61
61
|
publish?: TSdCliPublishConfig;
|
|
62
62
|
}
|
|
@@ -107,4 +107,4 @@ export interface ISdCliClientPackageCordovaConfig {
|
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
export type TSdCliCordovaPlatform = "browser" | "ios" | "android" | "
|
|
110
|
+
export type TSdCliCordovaPlatform = "browser" | "ios" | "android" | "electron";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import readline from "readline";
|
|
2
|
+
import { Writable } from "stream";
|
|
3
|
+
import crypto from "crypto";
|
|
4
|
+
import { FsUtil } from "@simplysm/sd-core-node";
|
|
5
|
+
import os from "os";
|
|
6
|
+
|
|
7
|
+
export class SdCliFileCrypto {
|
|
8
|
+
public async encryptAsync(filePath: string): Promise<void> {
|
|
9
|
+
if (!FsUtil.exists(filePath)) {
|
|
10
|
+
throw new Error(`파일 '${filePath}'을 찾을 수 없습니다.`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const key = await this._readKeyAsync("password: ");
|
|
14
|
+
if (!key) {
|
|
15
|
+
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const confirmKey = await this._readKeyAsync("confirm password: ");
|
|
19
|
+
if (key !== confirmKey) {
|
|
20
|
+
throw new Error("암호화키가 서로 다릅니다.");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this._encryptFile(filePath, key, filePath + ".enc");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async decryptAsync(encFilePath: string): Promise<void> {
|
|
27
|
+
if (!FsUtil.exists(encFilePath)) {
|
|
28
|
+
throw new Error(`파일 '${encFilePath}'을 찾을 수 없습니다.`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!encFilePath.endsWith(".enc")) {
|
|
32
|
+
throw new Error(`파일 ${encFilePath}의 확장자가 '.enc'가 아닙니다.`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const resultFilePath = encFilePath.slice(0, -4);
|
|
36
|
+
if (FsUtil.exists(resultFilePath)) {
|
|
37
|
+
process.stdout.write(`복호화 시, 현재 존재하는 '${resultFilePath}'파일을 덮어씁니다.${os.EOL}`, "utf-8");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const key = await this._readKeyAsync("password: ");
|
|
41
|
+
if (!key) {
|
|
42
|
+
throw new Error("암호화키를 반드시 입력해야 합니다.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
this._decryptFile(encFilePath, key, resultFilePath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private _encryptFile(filePath: string, key: string, encFilePath: string): void {
|
|
49
|
+
const iv = Buffer.alloc(16, 0);
|
|
50
|
+
const cipheriv = crypto.createCipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
51
|
+
|
|
52
|
+
const input = FsUtil.createReadStream(filePath);
|
|
53
|
+
const output = FsUtil.createWriteStream(encFilePath);
|
|
54
|
+
input.pipe(cipheriv).pipe(output);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private _decryptFile(encFilePath: string, key: string, filePath: string): void {
|
|
58
|
+
const iv = Buffer.alloc(16, 0);
|
|
59
|
+
const cipheriv = crypto.createDecipheriv("aes-192-cbc", crypto.scryptSync(key, "salt", 24), iv);
|
|
60
|
+
|
|
61
|
+
const input = FsUtil.createReadStream(encFilePath);
|
|
62
|
+
const output = FsUtil.createWriteStream(filePath);
|
|
63
|
+
input.pipe(cipheriv).pipe(output);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private async _readKeyAsync(message: string): Promise<string> {
|
|
67
|
+
process.stdout.write(message, "utf-8");
|
|
68
|
+
|
|
69
|
+
return await new Promise((resolve) => {
|
|
70
|
+
const rl = readline.createInterface({
|
|
71
|
+
input: process.stdin,
|
|
72
|
+
output: new Writable({
|
|
73
|
+
write: (chunk, encoding, callback) => {
|
|
74
|
+
callback();
|
|
75
|
+
}
|
|
76
|
+
}),
|
|
77
|
+
terminal: true
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
rl.question(message, (answer) => {
|
|
81
|
+
process.stdout.write(os.EOL, "utf-8");
|
|
82
|
+
resolve(answer);
|
|
83
|
+
rl.close();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -14,7 +14,7 @@ export class SdCliLocalUpdate {
|
|
|
14
14
|
if (!conf.localUpdates) return;
|
|
15
15
|
|
|
16
16
|
const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
|
|
17
|
-
this._logger.debug("로컬 업데이트 구성"
|
|
17
|
+
this._logger.debug("로컬 업데이트 구성");
|
|
18
18
|
|
|
19
19
|
this._logger.log("로컬 라이브러리 업데이트 시작...");
|
|
20
20
|
for (const updatePathInfo of updatePathInfos) {
|
|
@@ -37,7 +37,7 @@ export class SdCliLocalUpdate {
|
|
|
37
37
|
if (!conf.localUpdates) return;
|
|
38
38
|
|
|
39
39
|
const updatePathInfos = await this._getUpdatePathInfosAsync(conf.localUpdates);
|
|
40
|
-
this._logger.debug("로컬 업데이트 구성"
|
|
40
|
+
this._logger.debug("로컬 업데이트 구성");
|
|
41
41
|
|
|
42
42
|
const watchPaths = (await updatePathInfos.mapManyAsync(async (item) => await this._getWatchPathsAsync(item.source))).distinct();
|
|
43
43
|
|
|
@@ -38,7 +38,7 @@ export class SdCliPrepare {
|
|
|
38
38
|
if (node.hasChildPerformanceWarning) {
|
|
39
39
|
node.parent.hasChildPerformanceWarning = true;
|
|
40
40
|
}
|
|
41
|
-
else if (usage.user + usage.system >
|
|
41
|
+
else if (usage.user + usage.system > 1000 * 1000 && node.kind !== 253) {
|
|
42
42
|
error(node, {
|
|
43
43
|
code: 9000,
|
|
44
44
|
category: ts.DiagnosticCategory.Warning,
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./builder/SdCliJsLibBuilder";
|
|
|
8
8
|
export * from "./builder/SdCliServerBuilder";
|
|
9
9
|
export * from "./builder/SdCliTsLibBuilder";
|
|
10
10
|
export * from "./commons";
|
|
11
|
+
export * from "./entry-points/SdCliFileCrypto";
|
|
11
12
|
export * from "./entry-points/SdCliLocalUpdate";
|
|
12
13
|
export * from "./entry-points/SdCliNpm";
|
|
13
14
|
export * from "./entry-points/SdCliPrepare";
|
|
@@ -16,9 +16,6 @@ import { FsUtil, Logger, PathUtil } from "@simplysm/sd-core-node";
|
|
|
16
16
|
import os from "os";
|
|
17
17
|
import { INpmConfig } from "../commons";
|
|
18
18
|
|
|
19
|
-
// TODO: 에러 메시지 처리
|
|
20
|
-
// TODO: forRoot에 있는 Provider 처리??
|
|
21
|
-
// TODO: CircularDependency
|
|
22
19
|
export class SdCliNgModuleGenerator {
|
|
23
20
|
private readonly _logger: Logger;
|
|
24
21
|
|
|
@@ -66,7 +63,7 @@ export class SdCliNgModuleGenerator {
|
|
|
66
63
|
public async runAsync(): Promise<void> {
|
|
67
64
|
this._logger.debug("Babel NgModule 정의 가져오기...");
|
|
68
65
|
const bbNgModules = this._getBbNgModuleDefs();
|
|
69
|
-
|
|
66
|
+
|
|
70
67
|
this._logger.debug("NgModule Preset 구성...");
|
|
71
68
|
const tsPreset = this._getTsGenNgModulePreset();
|
|
72
69
|
|
|
@@ -441,9 +441,9 @@ export class SdCliBbFileMetadata {
|
|
|
441
441
|
throw SdCliBbUtil.error("예상치 못한 방식의 코드가 발견되었습니다.", this.filePath, rawMeta);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
|
-
private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata>();
|
|
444
|
+
private readonly _getNgDecoArgCache = new Map<string, SdCliBbObjectMetadata | undefined>();
|
|
445
445
|
|
|
446
|
-
public getNgDecoArg(className: string): SdCliBbObjectMetadata {
|
|
446
|
+
public getNgDecoArg(className: string): SdCliBbObjectMetadata | undefined {
|
|
447
447
|
if (this._getNgDecoArgCache.has(className)) {
|
|
448
448
|
return this._getNgDecoArgCache.get(className)!;
|
|
449
449
|
}
|
|
@@ -529,9 +529,9 @@ export class SdCliBbFileMetadata {
|
|
|
529
529
|
}
|
|
530
530
|
});
|
|
531
531
|
|
|
532
|
-
if (result === undefined) {
|
|
533
|
-
|
|
534
|
-
}
|
|
532
|
+
// if (result === undefined) {
|
|
533
|
+
// throw new NeverEntryError(this.filePath + "," + className);
|
|
534
|
+
// }
|
|
535
535
|
|
|
536
536
|
this._getNgDecoArgCache.set(className, result);
|
|
537
537
|
return result;
|
|
@@ -27,13 +27,13 @@ export class SdCliBbNgModuleMetadata {
|
|
|
27
27
|
|
|
28
28
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
29
29
|
|
|
30
|
-
const expVal = argObjMeta
|
|
30
|
+
const expVal = argObjMeta?.getPropValue("exports") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "exports");
|
|
31
31
|
if (expVal !== undefined) {
|
|
32
32
|
const expMetas = this._getExportAndProviderMetas(expVal);
|
|
33
33
|
result.exports.push(...expMetas);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
const provVal = argObjMeta
|
|
36
|
+
const provVal = argObjMeta?.getPropValue("providers") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵmod", "providers");
|
|
37
37
|
if (provVal !== undefined) {
|
|
38
38
|
const provMetas = this._getExportAndProviderMetas(provVal);
|
|
39
39
|
result.providers.push(...provMetas);
|
|
@@ -140,7 +140,7 @@ export class SdCliBbNgDirectiveMetadata {
|
|
|
140
140
|
if (this._selectorCache !== undefined) return this._selectorCache;
|
|
141
141
|
|
|
142
142
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
143
|
-
const val = argObjMeta
|
|
143
|
+
const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵdir", "selector");
|
|
144
144
|
if (typeof val === "string") {
|
|
145
145
|
this._selectorCache = val;
|
|
146
146
|
return this._selectorCache;
|
|
@@ -162,7 +162,7 @@ export class SdCliBbNgComponentMetadata {
|
|
|
162
162
|
if (this._selectorCache !== undefined) return this._selectorCache;
|
|
163
163
|
|
|
164
164
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
165
|
-
const val = argObjMeta
|
|
165
|
+
const val = argObjMeta?.getPropValue("selector") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵcmp", "selector");
|
|
166
166
|
if (typeof val === "string") {
|
|
167
167
|
this._selectorCache = val;
|
|
168
168
|
return this._selectorCache;
|
|
@@ -184,7 +184,7 @@ export class SdCliBbNgPipeMetadata {
|
|
|
184
184
|
if (this._pipeNameCache !== undefined) return this._pipeNameCache;
|
|
185
185
|
|
|
186
186
|
const argObjMeta = this._fileMeta.getNgDecoArg(this._className);
|
|
187
|
-
const val = argObjMeta
|
|
187
|
+
const val = argObjMeta?.getPropValue("name") ?? this._fileMeta.getNgDecoPropValue(this._className, "ɵpipe", "name");
|
|
188
188
|
if (typeof val === "string") {
|
|
189
189
|
this._pipeNameCache = val;
|
|
190
190
|
return val;
|
|
@@ -59,6 +59,10 @@ export class SdCliBuildResultUtil {
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
public static getMessage(result: ISdCliPackageBuildResult): string {
|
|
62
|
+
if (result.code === "ESLintError") {
|
|
63
|
+
return result.message;
|
|
64
|
+
}
|
|
65
|
+
|
|
62
66
|
let str = "";
|
|
63
67
|
if (result.filePath !== undefined) {
|
|
64
68
|
str += `${result.filePath}(${result.line ?? 0}, ${result.char ?? 0}): `;
|