@simplysm/sd-cli 7.0.80 → 7.0.145
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.mjs +36 -6
- package/dist/build-tool/SdCliCordova.d.ts +4 -4
- package/dist/build-tool/SdCliCordova.mjs +108 -107
- package/dist/build-tool/SdCliElectron.d.ts +9 -0
- package/dist/build-tool/SdCliElectron.mjs +66 -0
- package/dist/build-tool/SdCliGithubApi.d.ts +14 -0
- package/dist/build-tool/SdCliGithubApi.mjs +96 -0
- package/dist/builder/SdCliClientBuilder.mjs +151 -65
- package/dist/builder/SdCliJsLibBuilder.mjs +4 -4
- package/dist/builder/SdCliServerBuilder.mjs +6 -7
- package/dist/builder/SdCliTsLibBuilder.mjs +4 -4
- package/dist/commons.d.ts +38 -11
- package/dist/entry-points/SdCliLocalUpdate.mjs +3 -3
- package/dist/entry-points/SdCliWorkspace.mjs +48 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +3 -1
- package/dist/ng-tools/babel/SdCliBbFileMetadata.mjs +2 -2
- package/dist/ng-tools/babel/SdCliBbRootMetadata.d.ts +1 -0
- package/dist/ng-tools/babel/SdCliBbRootMetadata.mjs +29 -3
- package/dist/packages/SdCliPackage.mjs +13 -2
- package/package.json +13 -7
- package/src/bin/sd-cli.ts +46 -7
- package/src/build-tool/SdCliCordova.ts +133 -141
- package/src/build-tool/SdCliElectron.ts +76 -0
- package/src/build-tool/SdCliGithubApi.ts +117 -0
- package/src/builder/SdCliClientBuilder.ts +165 -65
- package/src/builder/SdCliJsLibBuilder.ts +3 -3
- package/src/builder/SdCliServerBuilder.ts +6 -7
- package/src/builder/SdCliTsLibBuilder.ts +3 -3
- package/src/commons.ts +35 -11
- package/src/entry-points/SdCliLocalUpdate.ts +2 -2
- package/src/entry-points/SdCliWorkspace.ts +47 -6
- package/src/index.ts +2 -0
- package/src/ng-tools/babel/SdCliBbFileMetadata.ts +1 -1
- package/src/ng-tools/babel/SdCliBbRootMetadata.ts +30 -2
- package/src/packages/SdCliPackage.ts +18 -1
- package/tsconfig.json +3 -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
|
-
CommonJsUsageWarnPlugin,
|
|
11
10
|
DedupeModuleResolvePlugin,
|
|
12
11
|
JavaScriptOptimizerPlugin,
|
|
13
12
|
SuppressExtractedTextChunksWebpackPlugin
|
|
@@ -31,10 +30,10 @@ import { TransferSizePlugin } from "@angular-devkit/build-angular/src/webpack/pl
|
|
|
31
30
|
import { CssOptimizerPlugin } from "@angular-devkit/build-angular/src/webpack/plugins/css-optimizer-plugin";
|
|
32
31
|
import browserslist from "browserslist";
|
|
33
32
|
import { augmentAppWithServiceWorker } from "@angular-devkit/build-angular/src/utils/service-worker";
|
|
34
|
-
import { StringUtil } from "@simplysm/sd-core-common";
|
|
35
33
|
import { SdCliNgModuleGenerator } from "../ng-tools/SdCliNgModuleGenerator";
|
|
36
34
|
import { SdCliCordova } from "../build-tool/SdCliCordova";
|
|
37
35
|
import { SdCliNpmConfigUtil } from "../utils/SdCliNpmConfigUtil";
|
|
36
|
+
import electronBuilder from "electron-builder";
|
|
38
37
|
import LintResult = ESLint.LintResult;
|
|
39
38
|
|
|
40
39
|
export class SdCliClientBuilder extends EventEmitter {
|
|
@@ -84,8 +83,8 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
84
83
|
} : undefined);
|
|
85
84
|
|
|
86
85
|
// CORDOVA
|
|
87
|
-
if (this._config.cordova) {
|
|
88
|
-
this._cordova = new SdCliCordova(this._rootPath, this._config.cordova);
|
|
86
|
+
if (this._config.builder?.cordova) {
|
|
87
|
+
this._cordova = new SdCliCordova(this._rootPath, this._config.builder.cordova);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
|
|
@@ -97,6 +96,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
97
96
|
|
|
98
97
|
public async watchAsync(): Promise<NextHandleFunction[]> {
|
|
99
98
|
// DIST 비우기
|
|
99
|
+
await FsUtil.removeAsync(path.resolve(this._rootPath, ".electron"));
|
|
100
100
|
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
101
101
|
|
|
102
102
|
// NgModule 생성
|
|
@@ -109,10 +109,11 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// 빌드 준비
|
|
112
|
-
const
|
|
113
|
-
|
|
112
|
+
const webpackConfigs = (Object.keys(this._config.builder ?? { web: {} }) as ("web" | "cordova" | "electron")[])
|
|
113
|
+
.map((builderType) => this._getWebpackConfig(true, builderType));
|
|
114
|
+
const multiCompiler = webpack(webpackConfigs);
|
|
114
115
|
return await new Promise<NextHandleFunction[]>((resolve, reject) => {
|
|
115
|
-
|
|
116
|
+
multiCompiler.hooks.invalid.tap(this.constructor.name, (fileName) => {
|
|
116
117
|
if (fileName != null) {
|
|
117
118
|
this._logger.debug("파일변경 감지", fileName);
|
|
118
119
|
// NgModule 캐시 삭제
|
|
@@ -120,7 +121,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
120
121
|
}
|
|
121
122
|
});
|
|
122
123
|
|
|
123
|
-
|
|
124
|
+
multiCompiler.hooks.watchRun.tapAsync(this.constructor.name, async (args, callback) => {
|
|
124
125
|
this.emit("change");
|
|
125
126
|
|
|
126
127
|
// NgModule 생성
|
|
@@ -131,54 +132,58 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
131
132
|
this._logger.debug("Webpack 빌드 수행...");
|
|
132
133
|
});
|
|
133
134
|
|
|
134
|
-
compiler.
|
|
135
|
-
this.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
for (const compiler of multiCompiler.compilers) {
|
|
136
|
+
compiler.hooks.failed.tap(this.constructor.name, (err) => {
|
|
137
|
+
this.emit("complete", [{
|
|
138
|
+
filePath: undefined,
|
|
139
|
+
line: undefined,
|
|
140
|
+
char: undefined,
|
|
141
|
+
code: undefined,
|
|
142
|
+
severity: "error",
|
|
143
|
+
message: err.stack
|
|
144
|
+
}]);
|
|
145
|
+
reject(err);
|
|
146
|
+
return;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
146
149
|
|
|
147
|
-
|
|
150
|
+
multiCompiler.hooks.done.tap(this.constructor.name, async (multiStats) => {
|
|
148
151
|
// 결과 반환
|
|
149
|
-
const results = SdCliBuildResultUtil.convertFromWebpackStats(stats);
|
|
152
|
+
const results = multiStats.stats.mapMany((stats) => SdCliBuildResultUtil.convertFromWebpackStats(stats));
|
|
150
153
|
|
|
151
154
|
// .config.json 파일 쓰기
|
|
152
155
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
153
156
|
const packageKey = npmConfig.name.split("/").last()!;
|
|
154
157
|
|
|
155
|
-
const configDistPath =
|
|
158
|
+
const configDistPath = typeof this._config.server === "string"
|
|
156
159
|
? path.resolve(this._workspaceRootPath, "packages", this._config.server, "dist/www", packageKey, ".config.json")
|
|
157
160
|
: path.resolve(this._parsedTsconfig.options.outDir!, ".config.json");
|
|
158
161
|
await FsUtil.writeFileAsync(configDistPath, JSON.stringify(this._config.configs ?? {}, undefined, 2));
|
|
159
162
|
|
|
160
163
|
// 마무리
|
|
161
164
|
this._logger.debug("Webpack 빌드 완료");
|
|
162
|
-
resolve(
|
|
165
|
+
resolve(middlewares);
|
|
163
166
|
|
|
164
167
|
this.emit("complete", results);
|
|
165
168
|
});
|
|
166
169
|
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
const middlewares = multiCompiler.compilers.mapMany((compiler) => [
|
|
171
|
+
wdm(compiler, {
|
|
172
|
+
publicPath: compiler.options.output.publicPath,
|
|
173
|
+
index: "index.html",
|
|
174
|
+
stats: false
|
|
175
|
+
}),
|
|
176
|
+
whm(compiler, {
|
|
177
|
+
path: `${compiler.options.output.publicPath}__webpack_hmr`,
|
|
178
|
+
log: false
|
|
179
|
+
})
|
|
180
|
+
]);
|
|
177
181
|
});
|
|
178
182
|
}
|
|
179
183
|
|
|
180
184
|
public async buildAsync(): Promise<ISdCliPackageBuildResult[]> {
|
|
181
185
|
// DIST 비우기
|
|
186
|
+
await FsUtil.removeAsync(path.resolve(this._rootPath, ".electron"));
|
|
182
187
|
await FsUtil.removeAsync(this._parsedTsconfig.options.outDir!);
|
|
183
188
|
|
|
184
189
|
// NgModule 생성
|
|
@@ -186,17 +191,18 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
186
191
|
|
|
187
192
|
// 빌드
|
|
188
193
|
this._logger.debug("Webpack 빌드 수행...");
|
|
189
|
-
const
|
|
190
|
-
const
|
|
194
|
+
const builderTypes = (Object.keys(this._config.builder ?? { web: {} }) as ("web" | "cordova" | "electron")[]);
|
|
195
|
+
const webpackConfigs = builderTypes.map((builderType) => this._getWebpackConfig(false, builderType));
|
|
196
|
+
const multipleCompiler = webpack(webpackConfigs);
|
|
191
197
|
const buildResults = await new Promise<ISdCliPackageBuildResult[]>((resolve, reject) => {
|
|
192
|
-
|
|
193
|
-
if (err != null ||
|
|
198
|
+
multipleCompiler.run((err, multiStats) => {
|
|
199
|
+
if (err != null || multiStats == null) {
|
|
194
200
|
reject(err);
|
|
195
201
|
return;
|
|
196
202
|
}
|
|
197
203
|
|
|
198
204
|
// 결과 반환
|
|
199
|
-
const results = SdCliBuildResultUtil.convertFromWebpackStats(stats);
|
|
205
|
+
const results = multiStats.stats.mapMany((stats) => SdCliBuildResultUtil.convertFromWebpackStats(stats));
|
|
200
206
|
resolve(results);
|
|
201
207
|
});
|
|
202
208
|
});
|
|
@@ -206,11 +212,11 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
206
212
|
await FsUtil.writeFileAsync(targetPath, JSON.stringify(this._config.configs ?? {}, undefined, 2));
|
|
207
213
|
|
|
208
214
|
// service-worker 처리
|
|
209
|
-
if (FsUtil.exists(path.resolve(this._rootPath, "ngsw-config.json"))) {
|
|
215
|
+
if (builderTypes.includes("web") && FsUtil.exists(path.resolve(this._rootPath, "ngsw-config.json"))) {
|
|
210
216
|
const packageKey = this._getNpmConfig(this._rootPath)!.name.split("/").last()!;
|
|
211
217
|
await augmentAppWithServiceWorker(
|
|
212
218
|
PathUtil.posix(path.relative(this._workspaceRootPath, this._rootPath)) as any,
|
|
213
|
-
PathUtil.posix(path.relative(this._workspaceRootPath, this._parsedTsconfig.options.outDir!)) as any,
|
|
219
|
+
PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._parsedTsconfig.options.outDir!))) as any,
|
|
214
220
|
`/${packageKey}/`,
|
|
215
221
|
PathUtil.posix(path.relative(this._workspaceRootPath, path.resolve(this._rootPath, "ngsw-config.json")))
|
|
216
222
|
);
|
|
@@ -222,7 +228,74 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
222
228
|
await this._cordova.initializeAsync();
|
|
223
229
|
|
|
224
230
|
this._logger.debug("CORDOVA 빌드...");
|
|
225
|
-
await this._cordova.buildAsync(this._parsedTsconfig.options.outDir
|
|
231
|
+
await this._cordova.buildAsync(path.resolve(this._parsedTsconfig.options.outDir!, "cordova"));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ELECTRON
|
|
235
|
+
if (this._config.builder?.electron) {
|
|
236
|
+
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
237
|
+
|
|
238
|
+
const electronVersion = npmConfig.dependencies?.["electron"];
|
|
239
|
+
if (electronVersion === undefined) {
|
|
240
|
+
throw new Error("ELECTRON 빌드 패키지의 'dependencies'에는 'electron'이 반드시 포함되어야 합니다.");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const dotenvVersion = npmConfig.dependencies?.["dotenv"];
|
|
244
|
+
if (dotenvVersion === undefined) {
|
|
245
|
+
throw new Error("ELECTRON 빌드 패키지의 'dependencies'에는 'dotenv'가 반드시 포함되어야 합니다.");
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const electronSrcPath = path.resolve(this._rootPath, `.electron/src`);
|
|
249
|
+
const electronDistPath = path.resolve(this._rootPath, `.electron/dist`);
|
|
250
|
+
|
|
251
|
+
await FsUtil.writeJsonAsync(path.resolve(electronSrcPath, `package.json`), {
|
|
252
|
+
name: npmConfig.name,
|
|
253
|
+
version: npmConfig.version,
|
|
254
|
+
description: npmConfig.description,
|
|
255
|
+
main: "electron.js",
|
|
256
|
+
author: npmConfig.author,
|
|
257
|
+
license: npmConfig.license,
|
|
258
|
+
devDependencies: {
|
|
259
|
+
"electron": electronVersion.replace("^", "")
|
|
260
|
+
},
|
|
261
|
+
dependencies: {
|
|
262
|
+
"dotenv": dotenvVersion
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
await FsUtil.writeFileAsync(path.resolve(electronSrcPath, `.env`), [
|
|
267
|
+
"NODE_ENV=production",
|
|
268
|
+
`SD_VERSION=${npmConfig.version}`,
|
|
269
|
+
(this._config.builder.electron.icon !== undefined) ? `SD_ELECTRON_ICON=${this._config.builder.electron.icon}` : `SD_ELECTRON_ICON=favicon.ico`,
|
|
270
|
+
...(this._config.env !== undefined) ? Object.keys(this._config.env).map((key) => `${key}=${this._config.env![key]}`) : []
|
|
271
|
+
].filterExists().join("\n"));
|
|
272
|
+
|
|
273
|
+
let electronTsFileContent = await FsUtil.readFileAsync(path.resolve(this._rootPath, `src/electron.ts`));
|
|
274
|
+
electronTsFileContent = "require(\"dotenv\").config({ path: `${__dirname}\\\\.env` });\n" + electronTsFileContent;
|
|
275
|
+
const result = ts.transpileModule(electronTsFileContent, { compilerOptions: { module: ts.ModuleKind.CommonJS } });
|
|
276
|
+
await FsUtil.writeFileAsync(path.resolve(electronSrcPath, "electron.js"), result.outputText);
|
|
277
|
+
|
|
278
|
+
await electronBuilder.build({
|
|
279
|
+
targets: electronBuilder.Platform.WINDOWS.createTarget(),
|
|
280
|
+
config: {
|
|
281
|
+
appId: this._config.builder.electron.appId,
|
|
282
|
+
productName: npmConfig.description,
|
|
283
|
+
nsis: {},
|
|
284
|
+
directories: {
|
|
285
|
+
app: electronSrcPath,
|
|
286
|
+
output: electronDistPath
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await FsUtil.copyAsync(
|
|
292
|
+
path.resolve(this._rootPath, `.electron/dist/${npmConfig.description} Setup ${npmConfig.version}.exe`),
|
|
293
|
+
path.resolve(this._parsedTsconfig.options.outDir!, `electron/${npmConfig.description}-v${npmConfig.version}.exe`)
|
|
294
|
+
);
|
|
295
|
+
await FsUtil.copyAsync(
|
|
296
|
+
path.resolve(this._rootPath, `.electron/dist/${npmConfig.description} Setup ${npmConfig.version}.exe`),
|
|
297
|
+
path.resolve(this._parsedTsconfig.options.outDir!, `electron/${npmConfig.description}-latest.exe`)
|
|
298
|
+
);
|
|
226
299
|
}
|
|
227
300
|
|
|
228
301
|
// 마무리
|
|
@@ -237,23 +310,28 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
237
310
|
].map((p) => path.dirname(p));
|
|
238
311
|
}
|
|
239
312
|
|
|
240
|
-
private _getWebpackConfig(watch: boolean): webpack.Configuration {
|
|
313
|
+
private _getWebpackConfig(watch: boolean, builderType: "web" | "cordova" | "electron"): webpack.Configuration {
|
|
241
314
|
const workspaceNpmConfig = this._getNpmConfig(this._workspaceRootPath)!;
|
|
242
315
|
const workspaceName = workspaceNpmConfig.name;
|
|
243
316
|
|
|
244
317
|
const internalModuleCachePaths = watch ? this._getInternalModuleCachePaths(workspaceName) : undefined;
|
|
245
318
|
|
|
246
319
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
247
|
-
const pkgVersion = npmConfig.version;
|
|
248
|
-
const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
|
|
320
|
+
// const pkgVersion = npmConfig.version;
|
|
321
|
+
// const ngVersion = this._getNpmConfig(FsUtil.findAllParentChildDirPaths("node_modules/@angular/core", this._rootPath, this._workspaceRootPath)[0])!.version;
|
|
322
|
+
|
|
323
|
+
const workspacePkgLockContent = FsUtil.readFile(path.resolve(this._workspaceRootPath, "package-lock.json"));
|
|
249
324
|
|
|
250
325
|
const pkgKey = npmConfig.name.split("/").last()!;
|
|
251
|
-
const publicPath =
|
|
326
|
+
const publicPath = builderType === "web" ? `/${pkgKey}/` : watch ? `/${pkgKey}/${builderType}/` : ``;
|
|
252
327
|
|
|
253
328
|
const cacheBasePath = path.resolve(this._rootPath, ".cache");
|
|
254
|
-
const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
329
|
+
// const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
255
330
|
|
|
256
|
-
const distPath = (
|
|
331
|
+
const distPath = (builderType === "cordova" && !watch) ? path.resolve(this._cordova!.cordovaPath, "www")
|
|
332
|
+
: (builderType === "electron" && !watch) ? path.resolve(this._rootPath, ".electron/src")
|
|
333
|
+
: builderType === "web" ? this._parsedTsconfig.options.outDir
|
|
334
|
+
: `${this._parsedTsconfig.options.outDir}/${builderType}`;
|
|
257
335
|
|
|
258
336
|
const sassImplementation = new SassWorkerImplementation();
|
|
259
337
|
|
|
@@ -265,7 +343,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
265
343
|
return {
|
|
266
344
|
mode: watch ? "development" : "production",
|
|
267
345
|
devtool: false,
|
|
268
|
-
target: ["web", "es2015"],
|
|
346
|
+
target: builderType === "electron" ? ["electron-renderer", "es2015"] : ["web", "es2015"],
|
|
269
347
|
profile: false,
|
|
270
348
|
resolve: {
|
|
271
349
|
roots: [this._rootPath],
|
|
@@ -273,7 +351,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
273
351
|
symlinks: true,
|
|
274
352
|
modules: [this._workspaceRootPath, "node_modules"],
|
|
275
353
|
mainFields: ["es2015", "browser", "module", "main"],
|
|
276
|
-
conditionNames: ["es2015", "..."]
|
|
354
|
+
conditionNames: ["es2015", "..."],
|
|
277
355
|
},
|
|
278
356
|
resolveLoader: {
|
|
279
357
|
symlinks: true
|
|
@@ -316,14 +394,15 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
316
394
|
cache: {
|
|
317
395
|
type: "filesystem",
|
|
318
396
|
profile: watch ? undefined : false,
|
|
319
|
-
cacheDirectory: path.resolve(
|
|
397
|
+
cacheDirectory: path.resolve(cacheBasePath, "angular-webpack"),
|
|
320
398
|
maxMemoryGenerations: 1,
|
|
321
399
|
name: createHash("sha1")
|
|
322
|
-
.update(
|
|
323
|
-
.update(
|
|
400
|
+
.update(workspacePkgLockContent)
|
|
401
|
+
// .update(pkgVersion)
|
|
402
|
+
// .update(ngVersion)
|
|
324
403
|
.update(JSON.stringify(this._parsedTsconfig.options))
|
|
325
|
-
.update(this._workspaceRootPath)
|
|
326
|
-
.update(this._rootPath)
|
|
404
|
+
// .update(this._workspaceRootPath)
|
|
405
|
+
// .update(this._rootPath)
|
|
327
406
|
.update(JSON.stringify(this._config))
|
|
328
407
|
.update(watch.toString())
|
|
329
408
|
.digest("hex")
|
|
@@ -430,7 +509,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
430
509
|
{
|
|
431
510
|
loader: "@angular-devkit/build-angular/src/babel/webpack-loader",
|
|
432
511
|
options: {
|
|
433
|
-
cacheDirectory: path.resolve(
|
|
512
|
+
cacheDirectory: path.resolve(cacheBasePath, "babel-webpack"),
|
|
434
513
|
scriptTarget: ts.ScriptTarget.ES2017,
|
|
435
514
|
aot: true,
|
|
436
515
|
optimize: !watch,
|
|
@@ -504,7 +583,9 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
504
583
|
]
|
|
505
584
|
},
|
|
506
585
|
plugins: [
|
|
507
|
-
new NodePolyfillPlugin(
|
|
586
|
+
new NodePolyfillPlugin({
|
|
587
|
+
excludeAliases: builderType === "electron" ? ["process"] : []
|
|
588
|
+
}),
|
|
508
589
|
new NamedChunksPlugin(),
|
|
509
590
|
new DedupeModuleResolvePlugin(),
|
|
510
591
|
new webpack.ProgressPlugin({
|
|
@@ -518,7 +599,6 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
518
599
|
}
|
|
519
600
|
}
|
|
520
601
|
}),
|
|
521
|
-
new CommonJsUsageWarnPlugin(),
|
|
522
602
|
...watch ? [] : [
|
|
523
603
|
new LicenseWebpackPlugin({
|
|
524
604
|
stats: { warnings: false, errors: false },
|
|
@@ -529,7 +609,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
529
609
|
],
|
|
530
610
|
new CopyWebpackPlugin({
|
|
531
611
|
patterns: [
|
|
532
|
-
...["favicon.ico", "assets/", "manifest.
|
|
612
|
+
...["favicon.ico", "assets/", "manifest.json"].map((item) => ({
|
|
533
613
|
context: this._rootPath,
|
|
534
614
|
to: item,
|
|
535
615
|
from: `src/${item}`,
|
|
@@ -546,11 +626,31 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
546
626
|
},
|
|
547
627
|
priority: 0
|
|
548
628
|
})),
|
|
549
|
-
...
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
629
|
+
...builderType === "cordova" && watch ? this._cordova!.platforms.mapMany((platform) => [
|
|
630
|
+
{
|
|
631
|
+
context: this._cordova!.cordovaPath,
|
|
632
|
+
to: `cordova-${platform}/plugins`,
|
|
633
|
+
from: `platforms/${platform}/platform_www/plugins`,
|
|
634
|
+
noErrorOnMissing: true
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
context: this._cordova!.cordovaPath,
|
|
638
|
+
to: `cordova-${platform}/cordova.js`,
|
|
639
|
+
from: `platforms/${platform}/platform_www/cordova.js`
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
context: this._cordova!.cordovaPath,
|
|
643
|
+
to: `cordova-${platform}/cordova_plugins.js`,
|
|
644
|
+
from: `platforms/${platform}/platform_www/cordova_plugins.js`,
|
|
645
|
+
noErrorOnMissing: true
|
|
646
|
+
},
|
|
647
|
+
{
|
|
648
|
+
context: this._cordova!.cordovaPath,
|
|
649
|
+
to: `cordova-${platform}/config.xml`,
|
|
650
|
+
from: `platforms/${platform}/www/config.xml`,
|
|
651
|
+
noErrorOnMissing: true
|
|
652
|
+
}
|
|
653
|
+
]) : []
|
|
554
654
|
]
|
|
555
655
|
}),
|
|
556
656
|
...watch ? [
|
|
@@ -603,7 +703,7 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
603
703
|
cache: {
|
|
604
704
|
enabled: true,
|
|
605
705
|
basePath: cacheBasePath,
|
|
606
|
-
path:
|
|
706
|
+
path: path.resolve(cacheBasePath, "index-webpack")
|
|
607
707
|
},
|
|
608
708
|
postTransform: undefined,
|
|
609
709
|
optimization: {
|
|
@@ -25,15 +25,15 @@ export class SdCliJsLibBuilder extends EventEmitter {
|
|
|
25
25
|
|
|
26
26
|
const relatedPaths = await this.getRelatedPathsAsync();
|
|
27
27
|
const watcher = SdFsWatcher.watch(relatedPaths);
|
|
28
|
-
watcher.onChange({}, async (
|
|
29
|
-
const changeFilePaths =
|
|
28
|
+
watcher.onChange({}, async (changedInfos) => {
|
|
29
|
+
const changeFilePaths = changedInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
30
30
|
if (changeFilePaths.length === 0) return;
|
|
31
31
|
|
|
32
32
|
this._logger.debug("파일 변경 감지");
|
|
33
33
|
this.emit("change");
|
|
34
34
|
const watchBuildResults: ISdCliPackageBuildResult[] = [];
|
|
35
35
|
|
|
36
|
-
const lintFilePaths =
|
|
36
|
+
const lintFilePaths = changedInfos.filter((item) => ["add", "change"].includes(item.event)).map((item) => item.path);
|
|
37
37
|
if (lintFilePaths.length > 0) {
|
|
38
38
|
watchBuildResults.push(...await this._linter.lintAsync(lintFilePaths));
|
|
39
39
|
}
|
|
@@ -187,11 +187,12 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
187
187
|
|
|
188
188
|
const npmConfig = this._getNpmConfig(this._rootPath)!;
|
|
189
189
|
const pkgKey = npmConfig.name.split("/").last()!;
|
|
190
|
-
const pkgVersion = npmConfig.version;
|
|
190
|
+
// const pkgVersion = npmConfig.version;
|
|
191
191
|
|
|
192
|
-
const
|
|
193
|
-
const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
192
|
+
const workspacePkgLockContent = FsUtil.readFile(path.resolve(this._workspaceRootPath, "package-lock.json"));
|
|
194
193
|
|
|
194
|
+
const cacheBasePath = path.resolve(this._rootPath, ".cache");
|
|
195
|
+
// const cachePath = path.resolve(cacheBasePath, pkgVersion);
|
|
195
196
|
|
|
196
197
|
let prevProgressMessage = "";
|
|
197
198
|
return {
|
|
@@ -241,13 +242,11 @@ export class SdCliServerBuilder extends EventEmitter {
|
|
|
241
242
|
cache: {
|
|
242
243
|
type: "filesystem",
|
|
243
244
|
profile: watch ? undefined : false,
|
|
244
|
-
cacheDirectory: path.resolve(
|
|
245
|
+
cacheDirectory: path.resolve(cacheBasePath, "server-webpack"),
|
|
245
246
|
maxMemoryGenerations: 1,
|
|
246
247
|
name: createHash("sha1")
|
|
247
|
-
.update(
|
|
248
|
+
.update(workspacePkgLockContent)
|
|
248
249
|
.update(JSON.stringify(this._parsedTsconfig.options))
|
|
249
|
-
.update(this._workspaceRootPath)
|
|
250
|
-
.update(this._rootPath)
|
|
251
250
|
.update(JSON.stringify(this._config))
|
|
252
251
|
.update(watch.toString())
|
|
253
252
|
.digest("hex")
|
|
@@ -115,8 +115,8 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
115
115
|
this._logger.debug("변경감지 구성...");
|
|
116
116
|
const relatedPaths = await this.getAllRelatedPathsAsync();
|
|
117
117
|
const watcher = SdFsWatcher.watch(relatedPaths);
|
|
118
|
-
watcher.onChange({}, async (
|
|
119
|
-
const changeFilePaths =
|
|
118
|
+
watcher.onChange({}, async (changedInfos) => {
|
|
119
|
+
const changeFilePaths = changedInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
120
120
|
if (changeFilePaths.length === 0) return;
|
|
121
121
|
|
|
122
122
|
this._logger.debug("파일 변경 감지", changeFilePaths);
|
|
@@ -153,7 +153,7 @@ export class SdCliTsLibBuilder extends EventEmitter {
|
|
|
153
153
|
this._logger.debug("린트...");
|
|
154
154
|
const lintFilePaths = [
|
|
155
155
|
...watchBuildPack.affectedSourceFiles.map((item) => item.fileName),
|
|
156
|
-
...
|
|
156
|
+
...changedInfos.filter((item) => ["add", "change"].includes(item.event)).map((item) => item.path)
|
|
157
157
|
];
|
|
158
158
|
if (lintFilePaths.length > 0) {
|
|
159
159
|
watchBuildResults.push(...await this._linter.lintAsync(lintFilePaths, watchBuildPack.program));
|
package/src/commons.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
export interface INpmConfig {
|
|
2
2
|
name: string;
|
|
3
3
|
version: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
author?: string;
|
|
6
|
+
license?: string;
|
|
7
|
+
repository: string | {
|
|
8
|
+
type: string;
|
|
9
|
+
url: string;
|
|
10
|
+
directory?: string;
|
|
11
|
+
};
|
|
4
12
|
type?: "module";
|
|
5
13
|
workspaces?: string[];
|
|
6
14
|
main?: string;
|
|
@@ -63,14 +71,18 @@ export interface ISdCliServerPackageConfig {
|
|
|
63
71
|
|
|
64
72
|
export interface ISdCliClientPackageConfig {
|
|
65
73
|
type: "client";
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
builder?: {
|
|
75
|
+
web?: ISdCliClientBuilderWebConfig;
|
|
76
|
+
cordova?: ISdCliClientBuilderCordovaConfig;
|
|
77
|
+
electron?: ISdCliClientBuilderElectronConfig;
|
|
78
|
+
};
|
|
79
|
+
server: string | { port: number };
|
|
68
80
|
env?: Record<string, string>;
|
|
69
81
|
configs?: Record<string, any>;
|
|
70
82
|
publish?: TSdCliPublishConfig;
|
|
71
83
|
}
|
|
72
84
|
|
|
73
|
-
export type TSdCliPublishConfig = ISdCliFtpPublishConfig | ISdCliLocalDirectoryPublishConfig;
|
|
85
|
+
export type TSdCliPublishConfig = ISdCliFtpPublishConfig | ISdCliLocalDirectoryPublishConfig | ISdCliGithubPublishConfig;
|
|
74
86
|
|
|
75
87
|
export interface ISdCliFtpPublishConfig {
|
|
76
88
|
type: "ftp" | "ftps" | "sftp";
|
|
@@ -86,17 +98,26 @@ export interface ISdCliLocalDirectoryPublishConfig {
|
|
|
86
98
|
path: string;
|
|
87
99
|
}
|
|
88
100
|
|
|
89
|
-
export interface
|
|
90
|
-
|
|
101
|
+
export interface ISdCliGithubPublishConfig {
|
|
102
|
+
type: "github";
|
|
103
|
+
apiKey: string;
|
|
104
|
+
files: { from: string; to: string }[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface ISdCliClientBuilderWebConfig {
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface ISdCliClientBuilderCordovaConfig {
|
|
91
111
|
appId: string;
|
|
92
112
|
appName: string;
|
|
93
113
|
plugins?: string[];
|
|
94
114
|
icon?: string;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
115
|
+
debug?: boolean;
|
|
116
|
+
target?: {
|
|
117
|
+
browser?: {};
|
|
118
|
+
android?: {
|
|
119
|
+
bundle?: boolean;
|
|
120
|
+
sign?: {
|
|
100
121
|
keystore: string;
|
|
101
122
|
storePassword: string;
|
|
102
123
|
alias: string;
|
|
@@ -107,4 +128,7 @@ export interface ISdCliClientPackageCordovaConfig {
|
|
|
107
128
|
};
|
|
108
129
|
}
|
|
109
130
|
|
|
110
|
-
export
|
|
131
|
+
export interface ISdCliClientBuilderElectronConfig {
|
|
132
|
+
appId: string;
|
|
133
|
+
icon?: string;
|
|
134
|
+
}
|
|
@@ -42,8 +42,8 @@ export class SdCliLocalUpdate {
|
|
|
42
42
|
const watchPaths = (await updatePathInfos.mapManyAsync(async (item) => await this._getWatchPathsAsync(item.source))).distinct();
|
|
43
43
|
|
|
44
44
|
const watcher = SdFsWatcher.watch(watchPaths);
|
|
45
|
-
watcher.onChange({ delay: 1000 }, async (
|
|
46
|
-
const changeFilePaths =
|
|
45
|
+
watcher.onChange({ delay: 1000 }, async (changedInfos) => {
|
|
46
|
+
const changeFilePaths = changedInfos.filter((item) => ["add", "change", "unlink"].includes(item.event)).map((item) => item.path);
|
|
47
47
|
if (changeFilePaths.length === 0) return;
|
|
48
48
|
|
|
49
49
|
this._logger.log("로컬 라이브러리 변경감지...");
|
|
@@ -80,9 +80,33 @@ export class SdCliWorkspace {
|
|
|
80
80
|
if (pkg.config.type === "client") {
|
|
81
81
|
const middlewares = (await pkg.watchAsync()) as NextHandleFunction[];
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
if (typeof pkg.config.server === "string") {
|
|
84
|
+
const serverInfo = this._serverInfoMap.getOrCreate(pkg.config.server, { middlewares: [], clientInfos: [] });
|
|
85
|
+
serverInfo.middlewares.push(...middlewares);
|
|
86
|
+
serverInfo.clientInfos.push({
|
|
87
|
+
pkgKey: pkg.name.split("/").last()!,
|
|
88
|
+
platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
|
|
89
|
+
cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else { // DEV SERVER
|
|
93
|
+
const serverInfo = this._serverInfoMap.getOrCreate("_", { middlewares: [], clientInfos: [] });
|
|
94
|
+
if (serverInfo.server === undefined) {
|
|
95
|
+
const server = new SdServiceServer({
|
|
96
|
+
rootPath: process.cwd(),
|
|
97
|
+
services: [],
|
|
98
|
+
port: pkg.config.server.port
|
|
99
|
+
});
|
|
100
|
+
await server.listenAsync();
|
|
101
|
+
serverInfo.server = server;
|
|
102
|
+
serverInfo.server.devMiddlewares = middlewares;
|
|
103
|
+
serverInfo.clientInfos.push({
|
|
104
|
+
pkgKey: pkg.name.split("/").last()!,
|
|
105
|
+
platforms: pkg.config.builder ? Object.keys(pkg.config.builder) : ["web"],
|
|
106
|
+
cordovaTargets: pkg.config.builder?.cordova?.target ? Object.keys(pkg.config.builder.cordova.target) : ["browser"]
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
86
110
|
}
|
|
87
111
|
else {
|
|
88
112
|
await pkg.watchAsync();
|
|
@@ -345,11 +369,28 @@ export class SdCliWorkspace {
|
|
|
345
369
|
const portStr = serverInfo.server.options.port.toString();
|
|
346
370
|
|
|
347
371
|
for (const clientInfo of serverInfo.clientInfos) {
|
|
348
|
-
|
|
372
|
+
for (const platform of clientInfo.platforms) {
|
|
373
|
+
if (platform === "web") {
|
|
374
|
+
clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/`);
|
|
375
|
+
}
|
|
376
|
+
else if (platform === "electron") {
|
|
377
|
+
clientHrefs.push(`sd-cli run-electron ${clientInfo.pkgKey} http://localhost:${portStr}`);
|
|
378
|
+
}
|
|
379
|
+
else if (platform === "cordova") {
|
|
380
|
+
for (const target of clientInfo.cordovaTargets) {
|
|
381
|
+
if (target === "browser") {
|
|
382
|
+
clientHrefs.push(`${protocolStr}://localhost:${portStr}/${clientInfo.pkgKey}/${platform}/`);
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
clientHrefs.push(`sd-cli run-cordova ${clientInfo.pkgKey} http://[IP]:${portStr}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
349
390
|
}
|
|
350
391
|
}
|
|
351
392
|
if (clientHrefs.length > 0) {
|
|
352
|
-
this._logger.log(`오픈된
|
|
393
|
+
this._logger.log(`오픈된 클라이언트:\n${clientHrefs.join("\n")}`);
|
|
353
394
|
}
|
|
354
395
|
}
|
|
355
396
|
}
|
|
@@ -357,5 +398,5 @@ export class SdCliWorkspace {
|
|
|
357
398
|
interface IServerInfo {
|
|
358
399
|
server?: SdServiceServer;
|
|
359
400
|
middlewares: NextHandleFunction[];
|
|
360
|
-
clientInfos: { pkgKey: string }[];
|
|
401
|
+
clientInfos: { pkgKey: string; platforms: string[]; cordovaTargets: string[] }[];
|
|
361
402
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from "./build-tool/SdCliCacheCompilerHost";
|
|
2
2
|
export * from "./build-tool/SdCliCordova";
|
|
3
|
+
export * from "./build-tool/SdCliElectron";
|
|
4
|
+
export * from "./build-tool/SdCliGithubApi";
|
|
3
5
|
export * from "./build-tool/SdCliIndexFileGenerator";
|
|
4
6
|
export * from "./build-tool/SdCliNgCacheCompilerHost";
|
|
5
7
|
export * from "./build-tool/SdCliPackageLinter";
|