@simplysm/sd-cli 7.0.25 → 7.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.
- package/.eslintrc.cjs +2 -2
- package/dist/bin/sd-cli.mjs +3 -1
- package/dist/build-tool/SdCliNgCacheCompilerHost.mjs +3 -3
- package/dist/builder/SdCliClientBuilder.d.ts +20 -0
- package/dist/builder/SdCliClientBuilder.mjs +417 -0
- package/dist/builder/SdCliJsLibBuilder.mjs +2 -2
- package/dist/builder/SdCliServerBuilder.d.ts +6 -4
- package/dist/builder/SdCliServerBuilder.mjs +175 -100
- package/dist/builder/SdCliTsLibBuilder.d.ts +5 -3
- package/dist/builder/SdCliTsLibBuilder.mjs +20 -21
- package/dist/commons.d.ts +10 -1
- package/dist/entry-points/SdCliLocalUpdate.mjs +15 -9
- package/dist/entry-points/SdCliNpm.mjs +8 -4
- package/dist/entry-points/SdCliPrepare.mjs +3 -2
- package/dist/entry-points/SdCliWorkspace.d.ts +1 -0
- package/dist/entry-points/SdCliWorkspace.mjs +57 -24
- package/dist/packages/SdCliPackage.d.ts +4 -4
- package/dist/packages/SdCliPackage.mjs +17 -17
- package/dist/utils/SdCliBuildResultUtil.mjs +4 -5
- package/dist/utils/SdCliNpmConfigUtil.d.ts +7 -0
- package/dist/utils/SdCliNpmConfigUtil.mjs +15 -0
- package/package.json +18 -7
- package/src/bin/sd-cli.ts +2 -0
- package/src/build-tool/SdCliNgCacheCompilerHost.ts +3 -3
- package/src/builder/SdCliClientBuilder.ts +451 -0
- package/src/builder/SdCliJsLibBuilder.ts +2 -2
- package/src/builder/SdCliServerBuilder.ts +195 -100
- package/src/builder/SdCliTsLibBuilder.ts +29 -24
- package/src/commons.ts +9 -1
- package/src/entry-points/SdCliLocalUpdate.ts +14 -8
- package/src/entry-points/SdCliNpm.ts +7 -3
- package/src/entry-points/SdCliPrepare.ts +2 -1
- package/src/entry-points/SdCliWorkspace.ts +65 -26
- package/src/packages/SdCliPackage.ts +18 -18
- package/src/utils/SdCliBuildResultUtil.ts +3 -4
- package/src/utils/SdCliNpmConfigUtil.ts +16 -0
- package/tsconfig.json +1 -1
|
@@ -8,9 +8,8 @@ import { SdCliBuildResultUtil } from "../utils/SdCliBuildResultUtil";
|
|
|
8
8
|
import { ErrorInfo } from "ts-loader/dist/interfaces";
|
|
9
9
|
import os from "os";
|
|
10
10
|
import { ESLint } from "eslint";
|
|
11
|
-
import * as webpackMerge from "webpack-merge";
|
|
12
11
|
import TerserPlugin from "terser-webpack-plugin";
|
|
13
|
-
import { StringUtil } from "@simplysm/sd-core-common";
|
|
12
|
+
import { ObjectUtil, StringUtil } from "@simplysm/sd-core-common";
|
|
14
13
|
import ESLintWebpackPlugin from "eslint-webpack-plugin";
|
|
15
14
|
import CopyWebpackPlugin from "copy-webpack-plugin";
|
|
16
15
|
import { LicenseWebpackPlugin } from "license-webpack-plugin";
|
|
@@ -45,26 +44,29 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
45
44
|
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
46
45
|
|
|
47
46
|
// 빌드 준비
|
|
48
|
-
const
|
|
47
|
+
const extModuleNames = this._getExternalModuleNames();
|
|
48
|
+
const webpackConfig = this._getWebpackConfig(true, extModuleNames);
|
|
49
49
|
const compiler = webpack(webpackConfig);
|
|
50
50
|
await new Promise<void>((resolve, reject) => {
|
|
51
51
|
compiler.hooks.watchRun.tapAsync(this.constructor.name, (args, callback) => {
|
|
52
52
|
this.emit("change");
|
|
53
|
-
callback();
|
|
54
|
-
|
|
55
53
|
this._logger.debug("Webpack 빌드 수행...");
|
|
54
|
+
callback();
|
|
56
55
|
});
|
|
57
56
|
|
|
58
|
-
compiler.watch({}, (err, stats) => {
|
|
57
|
+
compiler.watch({}, async (err, stats) => {
|
|
59
58
|
if (err != null || stats == null) {
|
|
60
59
|
reject(err);
|
|
61
60
|
return;
|
|
62
61
|
}
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
this.
|
|
63
|
+
// .config.json 파일 쓰기
|
|
64
|
+
await this._writeDistConfigFileAsync();
|
|
66
65
|
|
|
66
|
+
// 결과 반환
|
|
67
67
|
this._logger.debug("Webpack 빌드 완료");
|
|
68
|
+
const results = SdCliBuildResultUtil.convertFromWebpackStats(stats);
|
|
69
|
+
this.emit("complete", results);
|
|
68
70
|
resolve();
|
|
69
71
|
});
|
|
70
72
|
});
|
|
@@ -76,7 +78,8 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
76
78
|
|
|
77
79
|
// 빌드
|
|
78
80
|
this._logger.debug("Webpack 빌드 수행...");
|
|
79
|
-
const
|
|
81
|
+
const extModuleNames = this._getExternalModuleNames();
|
|
82
|
+
const webpackConfig = this._getWebpackConfig(false, extModuleNames);
|
|
80
83
|
const compiler = webpack(webpackConfig);
|
|
81
84
|
const buildResults = await new Promise<ISdCliPackageBuildResult[]>((resolve, reject) => {
|
|
82
85
|
compiler.run((err, stats) => {
|
|
@@ -85,18 +88,127 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
85
88
|
return;
|
|
86
89
|
}
|
|
87
90
|
|
|
88
|
-
// 결과
|
|
91
|
+
// 결과 반환
|
|
89
92
|
const results = SdCliBuildResultUtil.convertFromWebpackStats(stats);
|
|
90
93
|
resolve(results);
|
|
91
94
|
});
|
|
92
95
|
});
|
|
93
|
-
this._logger.debug("Webpack 빌드 완료");
|
|
94
96
|
|
|
97
|
+
// .config.json 파일 쓰기
|
|
98
|
+
await this._writeDistConfigFileAsync();
|
|
99
|
+
|
|
100
|
+
// pm2.json 파일 쓰기
|
|
101
|
+
await this._writeDistPm2ConfigFileAsync();
|
|
102
|
+
|
|
103
|
+
// iis 파일 쓰기
|
|
104
|
+
await this._writeDistIisConfigFileAsync();
|
|
105
|
+
|
|
106
|
+
// 배포용 package.json 파일 생성
|
|
107
|
+
await this._writeDistNpmConfigFileAsync(extModuleNames);
|
|
108
|
+
|
|
109
|
+
// 마무리
|
|
110
|
+
this._logger.debug("Webpack 빌드 완료");
|
|
95
111
|
return buildResults;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
|
-
private
|
|
114
|
+
private async _writeDistConfigFileAsync(): Promise<void> {
|
|
115
|
+
const configDistPath = path.resolve(this._parsedTsconfig.options.outDir!, ".config.json");
|
|
116
|
+
await FsUtil.writeFileAsync(configDistPath, JSON.stringify(this._config.configs ?? {}, undefined, 2));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private async _writeDistPm2ConfigFileAsync(): Promise<void> {
|
|
120
|
+
if (this._config.pm2 === undefined || this._config.pm2 === false) return;
|
|
121
|
+
|
|
122
|
+
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
123
|
+
const pm2DistPath = path.resolve(this._parsedTsconfig.options.outDir!, "pm2.json");
|
|
124
|
+
await FsUtil.writeFileAsync(
|
|
125
|
+
pm2DistPath,
|
|
126
|
+
JSON.stringify(
|
|
127
|
+
ObjectUtil.merge(
|
|
128
|
+
{
|
|
129
|
+
"name": npmConfig.name.replace(/@/g, "").replace(/\//g, "-"),
|
|
130
|
+
"script": path.basename(path.resolve(this._parsedTsconfig.options.outDir!, "main.mjs")),
|
|
131
|
+
"watch": true,
|
|
132
|
+
"watch_delay": 2000,
|
|
133
|
+
"ignore_watch": [
|
|
134
|
+
"node_modules",
|
|
135
|
+
"www"
|
|
136
|
+
].distinct(),
|
|
137
|
+
"interpreter": "node@" + process.versions.node,
|
|
138
|
+
"env": {
|
|
139
|
+
NODE_ENV: "production",
|
|
140
|
+
SD_VERSION: npmConfig.version,
|
|
141
|
+
TZ: "Asia/Seoul",
|
|
142
|
+
...this._config.env ? this._config.env : {}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
(typeof this._config.pm2 !== "boolean") ? this._config.pm2 : {},
|
|
146
|
+
{
|
|
147
|
+
arrayProcess: "concat"
|
|
148
|
+
}),
|
|
149
|
+
undefined,
|
|
150
|
+
2
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private async _writeDistIisConfigFileAsync(): Promise<void> {
|
|
156
|
+
if (this._config.iis === undefined || this._config.iis === false) return;
|
|
157
|
+
|
|
158
|
+
const iisDistPath = path.resolve(this._parsedTsconfig.options.outDir!, "web.config");
|
|
159
|
+
const serverExeFilePath = (this._config.iis !== true && "serverExeFilePath" in this._config.iis)
|
|
160
|
+
? (this._config.iis.serverExeFilePath ?? "C:\\Program Files\\nodejs\\node.exe")
|
|
161
|
+
: "C:\\Program Files\\nodejs\\node.exe";
|
|
162
|
+
await FsUtil.writeFileAsync(iisDistPath, `
|
|
163
|
+
<configuration>
|
|
164
|
+
<system.webServer>
|
|
165
|
+
<webSocket enabled="false" />
|
|
166
|
+
<handlers>
|
|
167
|
+
<add name="iisnode" path="main.js" verb="*" modules="iisnode" />
|
|
168
|
+
</handlers>
|
|
169
|
+
<iisnode nodeProcessCommandLine="${serverExeFilePath}"
|
|
170
|
+
watchedFiles="web.config;*.js"
|
|
171
|
+
loggingEnabled="true"
|
|
172
|
+
devErrorsEnabled="true" />
|
|
173
|
+
<rewrite>
|
|
174
|
+
<rules>
|
|
175
|
+
<rule name="main">
|
|
176
|
+
<action type="Rewrite" url="main.mjs" />
|
|
177
|
+
</rule>
|
|
178
|
+
</rules>
|
|
179
|
+
</rewrite>
|
|
180
|
+
<httpErrors errorMode="Detailed" />
|
|
181
|
+
</system.webServer>
|
|
182
|
+
</configuration>`.trim());
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private async _writeDistNpmConfigFileAsync(deps: string[]): Promise<void> {
|
|
186
|
+
const distNpmConfig = ObjectUtil.clone(this._getNpmConfig(this._rootPath))!;
|
|
187
|
+
distNpmConfig.dependencies = {};
|
|
188
|
+
for (const dep of deps) {
|
|
189
|
+
distNpmConfig.dependencies[dep] = "*";
|
|
190
|
+
}
|
|
191
|
+
delete distNpmConfig.optionalDependencies;
|
|
192
|
+
delete distNpmConfig.devDependencies;
|
|
193
|
+
delete distNpmConfig.peerDependencies;
|
|
194
|
+
|
|
195
|
+
if (this._config.pm2 !== undefined) {
|
|
196
|
+
distNpmConfig.scripts = { "start": "pm2 start pm2.json" };
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
await FsUtil.writeFileAsync(
|
|
200
|
+
path.resolve(this._parsedTsconfig.options.outDir!, "package.json"),
|
|
201
|
+
JSON.stringify(distNpmConfig, undefined, 2)
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private _getWebpackConfig(watch: boolean, extModuleNames: string[]): webpack.Configuration {
|
|
206
|
+
const internalModuleCachePaths = watch
|
|
207
|
+
? FsUtil.findAllParentChildDirPaths("node_modules/!(@simplysm)", this._rootPath, this._workspaceRootPath)
|
|
208
|
+
: undefined;
|
|
209
|
+
|
|
99
210
|
return {
|
|
211
|
+
mode: watch ? "development" : "production",
|
|
100
212
|
devtool: false,
|
|
101
213
|
target: ["node", "es2020"],
|
|
102
214
|
profile: false,
|
|
@@ -124,8 +236,46 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
124
236
|
outputModule: true
|
|
125
237
|
},
|
|
126
238
|
performance: { hints: false },
|
|
127
|
-
node:
|
|
239
|
+
node: {
|
|
240
|
+
__dirname: true
|
|
241
|
+
},
|
|
128
242
|
stats: "errors-warnings",
|
|
243
|
+
externals: extModuleNames,
|
|
244
|
+
...watch ? {
|
|
245
|
+
cache: { type: "memory", maxGenerations: 1 },
|
|
246
|
+
snapshot: {
|
|
247
|
+
immutablePaths: internalModuleCachePaths,
|
|
248
|
+
managedPaths: internalModuleCachePaths
|
|
249
|
+
}
|
|
250
|
+
} : {
|
|
251
|
+
cache: false
|
|
252
|
+
},
|
|
253
|
+
optimization: {
|
|
254
|
+
...watch ? {} : {
|
|
255
|
+
minimize: true,
|
|
256
|
+
minimizer: [
|
|
257
|
+
new TerserPlugin({
|
|
258
|
+
extractComments: false,
|
|
259
|
+
terserOptions: {
|
|
260
|
+
compress: true,
|
|
261
|
+
ecma: 2020,
|
|
262
|
+
sourceMap: false,
|
|
263
|
+
keep_classnames: true,
|
|
264
|
+
keep_fnames: true,
|
|
265
|
+
ie8: false,
|
|
266
|
+
safari10: false,
|
|
267
|
+
module: true,
|
|
268
|
+
format: {
|
|
269
|
+
comments: false
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
moduleIds: "deterministic",
|
|
276
|
+
chunkIds: watch ? "named" : "deterministic",
|
|
277
|
+
emitOnErrors: watch
|
|
278
|
+
},
|
|
129
279
|
module: {
|
|
130
280
|
strictExportPresence: true,
|
|
131
281
|
rules: [
|
|
@@ -135,6 +285,18 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
135
285
|
fullySpecified: false
|
|
136
286
|
}
|
|
137
287
|
},
|
|
288
|
+
...watch ? [
|
|
289
|
+
{
|
|
290
|
+
test: /\.m?js$/,
|
|
291
|
+
enforce: "pre" as const,
|
|
292
|
+
loader: "source-map-loader",
|
|
293
|
+
options: {
|
|
294
|
+
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
295
|
+
return !resourcePath.includes("node_modules") || (/@simplysm[\\/]sd/).test(resourcePath);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
] : [],
|
|
138
300
|
{
|
|
139
301
|
test: /\.ts$/,
|
|
140
302
|
exclude: /node_modules/,
|
|
@@ -160,6 +322,14 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
160
322
|
]
|
|
161
323
|
},
|
|
162
324
|
plugins: [
|
|
325
|
+
...watch ? [] : [
|
|
326
|
+
new LicenseWebpackPlugin({
|
|
327
|
+
stats: { warnings: false, errors: false },
|
|
328
|
+
perChunkOutput: false,
|
|
329
|
+
outputFilename: "3rd_party_licenses.txt",
|
|
330
|
+
skipChildCompilers: true
|
|
331
|
+
}) as any
|
|
332
|
+
],
|
|
163
333
|
new CopyWebpackPlugin({
|
|
164
334
|
patterns: ["assets/"].map((item) => ({
|
|
165
335
|
context: this._rootPath,
|
|
@@ -185,6 +355,8 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
185
355
|
}),
|
|
186
356
|
new ESLintWebpackPlugin({
|
|
187
357
|
context: this._rootPath,
|
|
358
|
+
eslintPath: path.resolve(this._workspaceRootPath, "node_modules", "eslint"),
|
|
359
|
+
exclude: ["node_modules"],
|
|
188
360
|
extensions: ["ts", "js", "mjs", "cjs"],
|
|
189
361
|
fix: false,
|
|
190
362
|
threads: false,
|
|
@@ -207,96 +379,21 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
207
379
|
}
|
|
208
380
|
return resultMessages.join(os.EOL);
|
|
209
381
|
}
|
|
210
|
-
})
|
|
382
|
+
})/*,
|
|
211
383
|
new webpack.ProgressPlugin({
|
|
212
384
|
handler: (per: number, msg: string, ...args: string[]) => {
|
|
213
385
|
const phaseText = msg ? ` - phase: ${msg}` : "";
|
|
214
386
|
const argsText = args.length > 0 ? ` - args: [${args.join(", ")}]` : "";
|
|
215
387
|
this._logger.debug(`Webpack 빌드 수행중...(${Math.round(per * 100)}%)${phaseText}${argsText}`);
|
|
216
388
|
}
|
|
217
|
-
})
|
|
389
|
+
})*/
|
|
218
390
|
]
|
|
219
391
|
};
|
|
220
392
|
}
|
|
221
393
|
|
|
222
|
-
private
|
|
223
|
-
const internalModuleCachePaths = FsUtil.findAllParentChildDirPaths("node_modules/!(@simplysm)", this._rootPath, this._workspaceRootPath);
|
|
224
|
-
|
|
225
|
-
const extModuleNames = this._findExternalModules(true).map((item) => item.name);
|
|
226
|
-
return webpackMerge.merge(this._webpackCommonConfig, {
|
|
227
|
-
mode: "development",
|
|
228
|
-
module: {
|
|
229
|
-
rules: [
|
|
230
|
-
{
|
|
231
|
-
test: /\.m?js$/,
|
|
232
|
-
enforce: "pre",
|
|
233
|
-
loader: "source-map-loader",
|
|
234
|
-
options: {
|
|
235
|
-
filterSourceMappingUrl: (mapUri: string, resourcePath: string) => {
|
|
236
|
-
return !resourcePath.includes("node_modules") || (/@simplysm[\\/]sd/).test(resourcePath);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
]
|
|
241
|
-
},
|
|
242
|
-
cache: { type: "memory", maxGenerations: 1 },
|
|
243
|
-
snapshot: {
|
|
244
|
-
immutablePaths: internalModuleCachePaths,
|
|
245
|
-
managedPaths: internalModuleCachePaths
|
|
246
|
-
},
|
|
247
|
-
optimization: {
|
|
248
|
-
moduleIds: "deterministic",
|
|
249
|
-
chunkIds: "named",
|
|
250
|
-
emitOnErrors: true
|
|
251
|
-
},
|
|
252
|
-
externals: extModuleNames
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
private _getWebpackBuildConfig(): webpack.Configuration {
|
|
257
|
-
const extModuleNames = this._findExternalModules(false).map((item) => item.name);
|
|
258
|
-
return webpackMerge.merge(this._webpackCommonConfig, {
|
|
259
|
-
mode: "production",
|
|
260
|
-
cache: false,
|
|
261
|
-
optimization: {
|
|
262
|
-
minimize: true,
|
|
263
|
-
minimizer: [
|
|
264
|
-
new TerserPlugin({
|
|
265
|
-
extractComments: false,
|
|
266
|
-
terserOptions: {
|
|
267
|
-
compress: true,
|
|
268
|
-
ecma: 2020,
|
|
269
|
-
sourceMap: false,
|
|
270
|
-
keep_classnames: true,
|
|
271
|
-
keep_fnames: true,
|
|
272
|
-
ie8: false,
|
|
273
|
-
safari10: false,
|
|
274
|
-
module: true,
|
|
275
|
-
format: {
|
|
276
|
-
comments: false
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
})
|
|
280
|
-
],
|
|
281
|
-
moduleIds: "deterministic",
|
|
282
|
-
chunkIds: "deterministic",
|
|
283
|
-
emitOnErrors: false
|
|
284
|
-
},
|
|
285
|
-
plugins: [
|
|
286
|
-
new LicenseWebpackPlugin({
|
|
287
|
-
stats: { warnings: false, errors: false },
|
|
288
|
-
perChunkOutput: false,
|
|
289
|
-
outputFilename: "3rd_party_licenses.txt",
|
|
290
|
-
skipChildCompilers: true
|
|
291
|
-
}) as any
|
|
292
|
-
],
|
|
293
|
-
externals: extModuleNames
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
private _findExternalModules(all: boolean): { name: string; path?: string }[] {
|
|
394
|
+
private _getExternalModuleNames(): string[] {
|
|
298
395
|
const loadedModuleNames: string[] = [];
|
|
299
|
-
const
|
|
396
|
+
const resultSet = new Set<string>();
|
|
300
397
|
|
|
301
398
|
const fn = (currPath: string): void => {
|
|
302
399
|
const npmConfig = this._getNpmConfig(currPath);
|
|
@@ -317,12 +414,11 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
317
414
|
|
|
318
415
|
const modulePath = FsUtil.findAllParentChildDirPaths("node_modules/" + moduleName, currPath, this._workspaceRootPath).first();
|
|
319
416
|
if (StringUtil.isNullOrEmpty(modulePath)) {
|
|
320
|
-
console.log(2, currPath, moduleName);
|
|
321
417
|
continue;
|
|
322
418
|
}
|
|
323
419
|
|
|
324
|
-
if (
|
|
325
|
-
|
|
420
|
+
if (FsUtil.exists(path.resolve(modulePath, "binding.gyp"))) {
|
|
421
|
+
resultSet.add(moduleName);
|
|
326
422
|
}
|
|
327
423
|
|
|
328
424
|
fn(modulePath);
|
|
@@ -334,13 +430,12 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
334
430
|
|
|
335
431
|
const optModulePath = FsUtil.findAllParentChildDirPaths("node_modules/" + optModuleName, currPath, this._workspaceRootPath).first();
|
|
336
432
|
if (StringUtil.isNullOrEmpty(optModulePath)) {
|
|
337
|
-
|
|
338
|
-
externalModules.push({ path: optModulePath, name: optModuleName });
|
|
433
|
+
resultSet.add(optModuleName);
|
|
339
434
|
continue;
|
|
340
435
|
}
|
|
341
436
|
|
|
342
|
-
if (
|
|
343
|
-
|
|
437
|
+
if (FsUtil.exists(path.resolve(optModulePath, "binding.gyp"))) {
|
|
438
|
+
resultSet.add(optModuleName);
|
|
344
439
|
}
|
|
345
440
|
|
|
346
441
|
fn(optModulePath);
|
|
@@ -349,7 +444,7 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
349
444
|
|
|
350
445
|
fn(this._rootPath);
|
|
351
446
|
|
|
352
|
-
return
|
|
447
|
+
return Array.from(resultSet.values());
|
|
353
448
|
}
|
|
354
449
|
|
|
355
450
|
private _getNpmConfig(pkgPath: string): INpmConfig | undefined {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISdCliPackageBuildResult } from "../commons";
|
|
1
|
+
import { INpmConfig, ISdCliPackageBuildResult } from "../commons";
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
3
|
import ts from "typescript";
|
|
4
4
|
import { FsUtil, Logger, PathUtil, SdFsWatcher } from "@simplysm/sd-core-node";
|
|
@@ -11,6 +11,7 @@ import { SdCliPackageLinter } from "../build-tool/SdCliPackageLinter";
|
|
|
11
11
|
import { SdCliCacheCompilerHost } from "../build-tool/SdCliCacheCompilerHost";
|
|
12
12
|
import { SdCliNgCacheCompilerHost } from "../build-tool/SdCliNgCacheCompilerHost";
|
|
13
13
|
import { NgCompiler } from "@angular/compiler-cli/src/ngtsc/core";
|
|
14
|
+
import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
|
|
14
15
|
|
|
15
16
|
export class SdCliTsLibBuilder extends EventEmitter {
|
|
16
17
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
@@ -26,10 +27,26 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
26
27
|
private _ngProgram?: NgtscProgram;
|
|
27
28
|
private _builder?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
private readonly _tsconfigFilePath: string;
|
|
31
|
+
private readonly _parsedTsconfig: ts.ParsedCommandLine;
|
|
32
|
+
private readonly _npmConfig: INpmConfig;
|
|
33
|
+
|
|
34
|
+
private readonly _isAngular: boolean;
|
|
35
|
+
|
|
36
|
+
public constructor(private readonly _rootPath: string) {
|
|
31
37
|
super();
|
|
32
38
|
this._linter = new SdCliPackageLinter(this._rootPath);
|
|
39
|
+
|
|
40
|
+
// tsconfig
|
|
41
|
+
this._tsconfigFilePath = path.resolve(this._rootPath, "tsconfig-build.json");
|
|
42
|
+
const tsconfig = FsUtil.readJson(this._tsconfigFilePath);
|
|
43
|
+
this._parsedTsconfig = ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath);
|
|
44
|
+
|
|
45
|
+
// package.json
|
|
46
|
+
this._npmConfig = FsUtil.readJson(path.resolve(this._rootPath, "package.json"));
|
|
47
|
+
|
|
48
|
+
// else
|
|
49
|
+
this._isAngular = SdCliNpmConfigUtil.getDependencies(this._npmConfig).defaults.includes("@angular/core");
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
public override on(event: "change", listener: () => void): this;
|
|
@@ -41,18 +58,15 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
41
58
|
public async watchAsync(): Promise<void> {
|
|
42
59
|
this.emit("change");
|
|
43
60
|
|
|
44
|
-
// TSCONFIG 읽기
|
|
45
|
-
const parsedTsconfig = await this._getParsedTsconfigAsync();
|
|
46
|
-
|
|
47
61
|
// DIST 비우기
|
|
48
|
-
await FsUtil.removeAsync(
|
|
62
|
+
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
49
63
|
|
|
50
64
|
// 프로그램 리로드
|
|
51
|
-
const buildPack = this._createSdBuildPack(
|
|
65
|
+
const buildPack = this._createSdBuildPack(this._parsedTsconfig);
|
|
52
66
|
|
|
53
67
|
const relatedPaths = await this.getAllRelatedPathsAsync();
|
|
54
68
|
const watcher = SdFsWatcher.watch(relatedPaths);
|
|
55
|
-
watcher.onChange(async (changeInfos) => {
|
|
69
|
+
watcher.onChange({}, async (changeInfos) => {
|
|
56
70
|
const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
57
71
|
if (changeFilePaths.length === 0) return;
|
|
58
72
|
|
|
@@ -65,7 +79,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
// 빌드
|
|
68
|
-
const watchBuildPack = this._createSdBuildPack(
|
|
82
|
+
const watchBuildPack = this._createSdBuildPack(this._parsedTsconfig);
|
|
69
83
|
|
|
70
84
|
// 린트
|
|
71
85
|
const watchBuildResults = await this._runBuilderAsync(watchBuildPack.builder, watchBuildPack.ngCompiler);
|
|
@@ -90,14 +104,11 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
90
104
|
}
|
|
91
105
|
|
|
92
106
|
public async buildAsync(): Promise<ISdCliPackageBuildResult[]> {
|
|
93
|
-
// TSCONFIG 읽기
|
|
94
|
-
const parsedTsconfig = await this._getParsedTsconfigAsync();
|
|
95
|
-
|
|
96
107
|
// DIST 비우기
|
|
97
|
-
await FsUtil.removeAsync(
|
|
108
|
+
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
98
109
|
|
|
99
110
|
// 프로그램 리로드
|
|
100
|
-
const buildPack = this._createSdBuildPack(
|
|
111
|
+
const buildPack = this._createSdBuildPack(this._parsedTsconfig);
|
|
101
112
|
|
|
102
113
|
// 빌드
|
|
103
114
|
const buildResults = await this._runBuilderAsync(buildPack.builder, buildPack.ngCompiler);
|
|
@@ -183,7 +194,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
183
194
|
}
|
|
184
195
|
catch (err) {
|
|
185
196
|
if (err instanceof sass.Exception) {
|
|
186
|
-
const matches =
|
|
197
|
+
const matches = (/^(.*\.sd\.scss) ([0-9]*):([0-9]*)/).exec(err.sassStack)!;
|
|
187
198
|
const filePath = path.resolve(matches[1].replace(/\.sd\.scss/, "").replace(/^\.:/, item => item.toUpperCase()));
|
|
188
199
|
const scssLine = matches[2];
|
|
189
200
|
const scssChar = matches[3];
|
|
@@ -195,7 +206,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
195
206
|
char: undefined,
|
|
196
207
|
code: undefined,
|
|
197
208
|
severity: "error",
|
|
198
|
-
message: `스타일(${scssLine}:${scssChar}): ${message}`
|
|
209
|
+
message: `스타일(${scssLine}:${scssChar}): ${message}\n${err.message}`
|
|
199
210
|
}];
|
|
200
211
|
}
|
|
201
212
|
|
|
@@ -223,7 +234,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
223
234
|
const affectedSourceFileSet: Set<ts.SourceFile> = new Set<ts.SourceFile>();
|
|
224
235
|
while (true) {
|
|
225
236
|
const result = this._builder.getSemanticDiagnosticsOfNextAffectedFile(undefined, (sourceFile) => {
|
|
226
|
-
if (ngCompiler
|
|
237
|
+
if (ngCompiler?.ignoreForDiagnostics.has(sourceFile) && sourceFile.fileName.endsWith(".ngtypecheck.ts")) {
|
|
227
238
|
const orgFileName = sourceFile.fileName.slice(0, -15) + ".ts";
|
|
228
239
|
const orgSourceFile = this._builder!.getSourceFile(orgFileName);
|
|
229
240
|
if (orgSourceFile) {
|
|
@@ -312,12 +323,6 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
312
323
|
return compilerHost;
|
|
313
324
|
}
|
|
314
325
|
}
|
|
315
|
-
|
|
316
|
-
private async _getParsedTsconfigAsync(): Promise<ts.ParsedCommandLine> {
|
|
317
|
-
const tsconfigFilePath = path.resolve(this._rootPath, "tsconfig-build.json");
|
|
318
|
-
const tsconfig = await FsUtil.readJsonAsync(tsconfigFilePath);
|
|
319
|
-
return ts.parseJsonConfigFileContent(tsconfig, ts.sys, this._rootPath);
|
|
320
|
-
}
|
|
321
326
|
}
|
|
322
327
|
|
|
323
328
|
interface IFileCache {
|
package/src/commons.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface ISdCliConfig {
|
|
|
40
40
|
localUpdates?: Record<string, string>;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export type TSdCliPackageConfig = ISdCliLibPackageConfig | ISdCliServerPackageConfig;
|
|
43
|
+
export type TSdCliPackageConfig = ISdCliLibPackageConfig | ISdCliServerPackageConfig | ISdCliClientPackageConfig;
|
|
44
44
|
|
|
45
45
|
export interface ISdCliLibPackageConfig {
|
|
46
46
|
type: "library";
|
|
@@ -50,4 +50,12 @@ export interface ISdCliLibPackageConfig {
|
|
|
50
50
|
export interface ISdCliServerPackageConfig {
|
|
51
51
|
type: "server";
|
|
52
52
|
env?: Record<string, string>;
|
|
53
|
+
configs?: Record<string, any>;
|
|
54
|
+
pm2?: Record<string, any> | boolean;
|
|
55
|
+
iis?: { serverExeFilePath?: string } | boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ISdCliClientPackageConfig {
|
|
59
|
+
type: "client";
|
|
60
|
+
server: string;
|
|
53
61
|
}
|
|
@@ -40,19 +40,25 @@ export class SdCliLocalUpdate {
|
|
|
40
40
|
const watchPaths = (await updatePathInfos.mapManyAsync(async (item) => await this._getWatchPathsAsync(item.source))).distinct();
|
|
41
41
|
|
|
42
42
|
const watcher = SdFsWatcher.watch(watchPaths);
|
|
43
|
-
watcher.onChange(async (changeInfos) => {
|
|
43
|
+
watcher.onChange({ delay: 1000 }, async (changeInfos) => {
|
|
44
44
|
const changeFilePaths = changeInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
45
45
|
if (changeFilePaths.length === 0) return;
|
|
46
46
|
|
|
47
47
|
this._logger.log("로컬 라이브러리 변경감지...");
|
|
48
48
|
for (const changedFilePath of changeFilePaths) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
if (!FsUtil.exists(changedFilePath)) continue;
|
|
50
|
+
|
|
51
|
+
for (const updatePathInfo of updatePathInfos) {
|
|
52
|
+
if (!PathUtil.isChildPath(changedFilePath, updatePathInfo.source)) continue;
|
|
53
|
+
|
|
54
|
+
const sourceRelPath = path.relative(updatePathInfo.source, changedFilePath);
|
|
55
|
+
if (sourceRelPath.includes("node_modules")) continue;
|
|
56
|
+
if (sourceRelPath.includes("package.json")) continue;
|
|
57
|
+
|
|
58
|
+
const targetFilePath = path.resolve(updatePathInfo.target, sourceRelPath);
|
|
59
|
+
|
|
60
|
+
this._logger.debug(`변경파일감지(복사): ${changedFilePath} => ${targetFilePath}`);
|
|
61
|
+
await FsUtil.copyAsync(changedFilePath, targetFilePath);
|
|
56
62
|
}
|
|
57
63
|
}
|
|
58
64
|
|
|
@@ -8,11 +8,15 @@ export class SdCliNpm {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
public async updateAsync(): Promise<void> {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
try {
|
|
12
|
+
this._logger.debug("업데이트할 패키지 확인...");
|
|
13
|
+
await SdProcess.spawnAsync("npm outdated", { cwd: this._rootPath });
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
this._logger.debug("업데이트 시작...");
|
|
15
|
-
await SdProcess.
|
|
19
|
+
await SdProcess.spawnAsync("npm update", { cwd: this._rootPath });
|
|
16
20
|
|
|
17
21
|
this._logger.debug("sd-cli 준비...");
|
|
18
22
|
await new SdCliPrepare().prepareAsync();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FsUtil, Logger } from "@simplysm/sd-core-node";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
2
3
|
|
|
3
4
|
export class SdCliPrepare {
|
|
4
5
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", this.constructor.name]);
|
|
@@ -11,7 +12,7 @@ export class SdCliPrepare {
|
|
|
11
12
|
|
|
12
13
|
private async _modifyTypescriptCodeForTypeCheckPerformanceWarning(): Promise<boolean> {
|
|
13
14
|
const fileUrl = await import.meta.resolve!("typescript");
|
|
14
|
-
const filePath = fileUrl
|
|
15
|
+
const filePath = fileURLToPath(fileUrl);
|
|
15
16
|
const fileContent = await FsUtil.readFileAsync(filePath);
|
|
16
17
|
const modifiedFileContent = fileContent.replace(`
|
|
17
18
|
function checkSourceElement(node) {
|