@simplysm/sd-cli 11.0.8 → 11.0.9
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-tools/SdCliCordova.d.ts +21 -0
- package/dist/build-tools/SdCliCordova.js +182 -0
- package/dist/build-tools/SdCliCordova.js.map +1 -0
- package/dist/build-tools/SdNgBundler.d.ts +5 -4
- package/dist/build-tools/SdNgBundler.js +46 -18
- package/dist/build-tools/SdNgBundler.js.map +1 -1
- package/dist/builders/SdCliClientBuilder.d.ts +1 -0
- package/dist/builders/SdCliClientBuilder.js +22 -2
- package/dist/builders/SdCliClientBuilder.js.map +1 -1
- package/dist/commons.d.ts +22 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/sd-cli.js +24 -0
- package/dist/sd-cli.js.map +1 -1
- package/lib/cordova-entry.js +22 -0
- package/package.json +8 -5
- package/src/build-tools/SdCliCordova.ts +240 -0
- package/src/build-tools/SdNgBundler.ts +61 -19
- package/src/builders/SdCliClientBuilder.ts +25 -2
- package/src/commons.ts +23 -0
- package/src/index.ts +1 -0
- package/src/sd-cli.ts +28 -0
package/dist/sd-cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Logger, LoggerSeverity } from "@simplysm/sd-core-node";
|
|
|
6
6
|
import { EventEmitter } from "events";
|
|
7
7
|
import { SdCliElectron } from "./entry/SdCliElectron";
|
|
8
8
|
import { SdCliLocalUpdate } from "./entry/SdCliLocalUpdate";
|
|
9
|
+
import { SdCliCordova } from "./build-tools/SdCliCordova";
|
|
9
10
|
Error.stackTraceLimit = Infinity;
|
|
10
11
|
EventEmitter.defaultMaxListeners = 0;
|
|
11
12
|
const argv = (await yargs(hideBin(process.argv))
|
|
@@ -134,6 +135,22 @@ const argv = (await yargs(hideBin(process.argv))
|
|
|
134
135
|
array: true,
|
|
135
136
|
describe: "옵션 설정"
|
|
136
137
|
}
|
|
138
|
+
}))
|
|
139
|
+
.command("run-cordova <platform> <package> <url>", "변경감지중인 플랫폼을 코도바 디바이스에 앱 형태로 띄웁니다.", (cmd) => cmd
|
|
140
|
+
.positional("platform", {
|
|
141
|
+
type: "string",
|
|
142
|
+
describe: "빌드 플랫폼(android,...)",
|
|
143
|
+
demandOption: true
|
|
144
|
+
})
|
|
145
|
+
.positional("package", {
|
|
146
|
+
type: "string",
|
|
147
|
+
describe: "패키지명",
|
|
148
|
+
demandOption: true
|
|
149
|
+
})
|
|
150
|
+
.positional("url", {
|
|
151
|
+
type: "string",
|
|
152
|
+
describe: "Webview로 오픈할 URL",
|
|
153
|
+
demandOption: true
|
|
137
154
|
}))
|
|
138
155
|
.parseAsync());
|
|
139
156
|
if (Boolean(argv.debug)) {
|
|
@@ -199,6 +216,13 @@ else if (argv._[0] === "build-electron-for-dev") {
|
|
|
199
216
|
pkgName: argv.package
|
|
200
217
|
});
|
|
201
218
|
}
|
|
219
|
+
else if (argv._[0] === "run-cordova") {
|
|
220
|
+
await SdCliCordova.runWebviewOnDeviceAsync({
|
|
221
|
+
platform: argv.platform,
|
|
222
|
+
pkgName: argv.package,
|
|
223
|
+
url: argv.url
|
|
224
|
+
});
|
|
225
|
+
}
|
|
202
226
|
else {
|
|
203
227
|
throw new Error(`명령어가 잘못 되었습니다.\n\t${argv._[0]}\n`);
|
|
204
228
|
}
|
package/dist/sd-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-cli.js","sourceRoot":"","sources":["../src/sd-cli.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,YAAY,EAAC,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAC,MAAM,EAAE,cAAc,EAAC,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAC,YAAY,EAAC,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"sd-cli.js","sourceRoot":"","sources":["../src/sd-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
const script = document.createElement("script");
|
|
4
|
+
script.onload = () => {
|
|
5
|
+
console.log("cordova.js Loaded");
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
if (process.env["NODE_ENV"] === "production") {
|
|
9
|
+
script.src = "cordova.js";
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
if (navigator.userAgent.toLowerCase().indexOf("android") !== -1) {
|
|
13
|
+
script.src = "cordova-android/cordova.js";
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
script.src = "cordova-browser/cordova.js";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
script.defer = true;
|
|
21
|
+
|
|
22
|
+
document.body.appendChild(script);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/sd-cli",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.9",
|
|
4
4
|
"description": "심플리즘 패키지 - CLI",
|
|
5
5
|
"author": "김석래",
|
|
6
6
|
"repository": {
|
|
@@ -23,11 +23,12 @@
|
|
|
23
23
|
"@angular/compiler-cli": "^16.2.9",
|
|
24
24
|
"@angular/core": "^16.2.9",
|
|
25
25
|
"@electron/rebuild": "^3.3.0",
|
|
26
|
-
"@simplysm/sd-core-common": "11.0.
|
|
27
|
-
"@simplysm/sd-core-node": "11.0.
|
|
28
|
-
"@simplysm/sd-service-server": "11.0.
|
|
29
|
-
"@simplysm/sd-storage": "11.0.
|
|
26
|
+
"@simplysm/sd-core-common": "11.0.9",
|
|
27
|
+
"@simplysm/sd-core-node": "11.0.9",
|
|
28
|
+
"@simplysm/sd-service-server": "11.0.9",
|
|
29
|
+
"@simplysm/sd-storage": "11.0.9",
|
|
30
30
|
"browserslist": "^4.22.1",
|
|
31
|
+
"cordova": "^12.0.0",
|
|
31
32
|
"electron": "^27.0.0",
|
|
32
33
|
"electron-builder": "^24.7.0",
|
|
33
34
|
"esbuild": "0.18.17",
|
|
@@ -37,11 +38,13 @@
|
|
|
37
38
|
"rxjs": "^7.8.1",
|
|
38
39
|
"sass": "^1.69.3",
|
|
39
40
|
"semver": "^7.5.4",
|
|
41
|
+
"xml2js": "^0.6.2",
|
|
40
42
|
"yargs": "^17.7.2",
|
|
41
43
|
"zone.js": "~0.13.3"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@types/eslint": "^8.44.4",
|
|
47
|
+
"@types/xml2js": "^0.4.12",
|
|
45
48
|
"@types/yargs": "^17.0.28"
|
|
46
49
|
},
|
|
47
50
|
"peerDependencies": {
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {INpmConfig, ISdCliClientBuilderCordovaConfig} from "../commons";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import {FsUtil, Logger, SdProcess} from "@simplysm/sd-core-node";
|
|
4
|
+
import xml2js from "xml2js";
|
|
5
|
+
|
|
6
|
+
const BIN_PATH = path.resolve(process.cwd(), "node_modules/.bin/cordova.cmd");
|
|
7
|
+
|
|
8
|
+
export class SdCliCordova {
|
|
9
|
+
protected readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliCordova"]);
|
|
10
|
+
|
|
11
|
+
private readonly _platforms: string[];
|
|
12
|
+
private readonly _npmConfig: INpmConfig;
|
|
13
|
+
|
|
14
|
+
public constructor(private readonly _opt: {
|
|
15
|
+
pkgPath: string;
|
|
16
|
+
config: ISdCliClientBuilderCordovaConfig;
|
|
17
|
+
cordovaPath: string;
|
|
18
|
+
}) {
|
|
19
|
+
this._platforms = Object.keys(this._opt.config.platform ?? {browser: {}});
|
|
20
|
+
this._npmConfig = FsUtil.readJson(path.resolve(this._opt.pkgPath, "package.json"));
|
|
21
|
+
// this._logger = Logger.get(["simplysm", "sd-cli", this.constructor.name, this._npmConfig.name]);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private async _execAsync(cmd: string, cwd: string): Promise<void> {
|
|
25
|
+
this._logger.debug(cmd);
|
|
26
|
+
const msg = await SdProcess.spawnAsync(cmd, {cwd});
|
|
27
|
+
this._logger.debug(msg);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async initializeAsync(): Promise<void> {
|
|
31
|
+
if (FsUtil.exists(this._opt.cordovaPath)) {
|
|
32
|
+
this._logger.log("이미 생성되어있는 '.cordova'를 사용합니다.");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
await this._execAsync(`${BIN_PATH} telemetry on`, this._opt.pkgPath);
|
|
36
|
+
|
|
37
|
+
// 프로젝트 생성
|
|
38
|
+
await this._execAsync(`${BIN_PATH} create "${this._opt.cordovaPath}" "${this._opt.config.appId}" "${this._opt.config.appName}"`, process.cwd());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// platforms 폴더 혹시 없으면 생성
|
|
42
|
+
await FsUtil.mkdirsAsync(path.resolve(this._opt.cordovaPath, "platforms"));
|
|
43
|
+
|
|
44
|
+
// www 폴더 혹시 없으면 생성
|
|
45
|
+
await FsUtil.mkdirsAsync(path.resolve(this._opt.cordovaPath, "www"));
|
|
46
|
+
|
|
47
|
+
// 미설치 빌드 플랫폼 신규 생성
|
|
48
|
+
const alreadyPlatforms = await FsUtil.readdirAsync(path.resolve(this._opt.cordovaPath, "platforms"));
|
|
49
|
+
for (const platform of this._platforms) {
|
|
50
|
+
if (!alreadyPlatforms.includes(platform)) {
|
|
51
|
+
await this._execAsync(`${BIN_PATH} platform add ${platform}`, this._opt.cordovaPath);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 설치 미빌드 플랫폼 삭제
|
|
56
|
+
for (const alreadyPlatform of alreadyPlatforms) {
|
|
57
|
+
if (!this._platforms.includes(alreadyPlatform)) {
|
|
58
|
+
await this._execAsync(`${BIN_PATH} platform remove ${alreadyPlatform}`, this._opt.cordovaPath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 설치된 미사용 플러그인 삭제
|
|
63
|
+
const pluginsFetch = FsUtil.exists(path.resolve(this._opt.cordovaPath, "plugins/fetch.json"))
|
|
64
|
+
? await FsUtil.readJsonAsync(path.resolve(this._opt.cordovaPath, "plugins/fetch.json"))
|
|
65
|
+
: undefined;
|
|
66
|
+
const alreadyPluginIds = pluginsFetch != undefined
|
|
67
|
+
? Object.values(pluginsFetch)
|
|
68
|
+
.map((item: any) => (item.source.id !== undefined ? item.source.id : item.source.url))
|
|
69
|
+
: [];
|
|
70
|
+
const usePlugins = ["cordova-plugin-ionic-webview", ...this._opt.config.plugins ?? []].distinct();
|
|
71
|
+
|
|
72
|
+
for (const alreadyPluginId of alreadyPluginIds) {
|
|
73
|
+
let hasPlugin = false;
|
|
74
|
+
for (const usePlugin of usePlugins) {
|
|
75
|
+
if (
|
|
76
|
+
(usePlugin.includes("@") && alreadyPluginId === usePlugin) ||
|
|
77
|
+
(!usePlugin.includes("@") && alreadyPluginId.replace(/@.*$/, "") === usePlugin)
|
|
78
|
+
) {
|
|
79
|
+
hasPlugin = true;
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!hasPlugin) {
|
|
85
|
+
await this._execAsync(`${BIN_PATH} plugin remove ${alreadyPluginId.replace(/@.*$/, "")}`, this._opt.cordovaPath);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 미설치 플러그인들 설치
|
|
90
|
+
for (const usePlugin of usePlugins) {
|
|
91
|
+
if (
|
|
92
|
+
(usePlugin.includes("@") && !alreadyPluginIds.includes(usePlugin)) ||
|
|
93
|
+
(!usePlugin.includes("@") && !alreadyPluginIds.map((alreadyPluginId) => alreadyPluginId.replace(/@.*$/, "")).includes(usePlugin))
|
|
94
|
+
) {
|
|
95
|
+
await this._execAsync(`${BIN_PATH} plugin add ${usePlugin}`, this._opt.cordovaPath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ANDROID SIGN 파일 복사
|
|
100
|
+
if (this._opt.config.platform?.android?.sign) {
|
|
101
|
+
await FsUtil.copyAsync(
|
|
102
|
+
path.resolve(this._opt.pkgPath, this._opt.config.platform.android.sign.keystore),
|
|
103
|
+
path.resolve(this._opt.cordovaPath, "android.keystore")
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
await FsUtil.removeAsync(path.resolve(this._opt.cordovaPath, "android.keystore"));
|
|
108
|
+
// SIGN을 안쓸경우 아래 파일이 생성되어 있으면 오류남
|
|
109
|
+
await FsUtil.removeAsync(path.resolve(this._opt.cordovaPath, "platforms/android/release-signing.properties"));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 빌드 옵션 파일 생성
|
|
113
|
+
await FsUtil.writeJsonAsync(
|
|
114
|
+
path.resolve(this._opt.cordovaPath, "build.json"),
|
|
115
|
+
{
|
|
116
|
+
...this._opt.config.platform?.android ? {
|
|
117
|
+
android: {
|
|
118
|
+
release: {
|
|
119
|
+
packageType: this._opt.config.platform.android.bundle ? "bundle" : "apk",
|
|
120
|
+
...this._opt.config.platform.android.sign ? {
|
|
121
|
+
keystore: path.resolve(this._opt.cordovaPath, "android.keystore"),
|
|
122
|
+
storePassword: this._opt.config.platform.android.sign.storePassword,
|
|
123
|
+
alias: this._opt.config.platform.android.sign.alias,
|
|
124
|
+
password: this._opt.config.platform.android.sign.password,
|
|
125
|
+
keystoreType: this._opt.config.platform.android.sign.keystoreType
|
|
126
|
+
} : {}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} : {}
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
// ICON 파일 복사
|
|
134
|
+
if (this._opt.config.icon !== undefined) {
|
|
135
|
+
await FsUtil.copyAsync(path.resolve(this._opt.cordovaPath, this._opt.config.icon), path.resolve(this._opt.cordovaPath, "res", "icon.png"));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
await FsUtil.removeAsync(path.resolve(this._opt.cordovaPath, "res", "icon.png"));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// CONFIG: 초기값 백업
|
|
142
|
+
const configFilePath = path.resolve(this._opt.cordovaPath, "config.xml");
|
|
143
|
+
const configBackFilePath = path.resolve(this._opt.cordovaPath, "config.xml.bak");
|
|
144
|
+
if (!FsUtil.exists(configBackFilePath)) {
|
|
145
|
+
await FsUtil.copyAsync(configFilePath, configBackFilePath);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// CONFIG: 초기값 읽기
|
|
149
|
+
const configFileContent = await FsUtil.readFileAsync(configBackFilePath);
|
|
150
|
+
const configXml = await xml2js.parseStringPromise(configFileContent);
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
// CONFIG: 버전 설정
|
|
154
|
+
configXml.widget.$.version = this._npmConfig.version;
|
|
155
|
+
|
|
156
|
+
// CONFIG: ICON 설정
|
|
157
|
+
if (this._opt.config.icon !== undefined) {
|
|
158
|
+
configXml["widget"]["icon"] = [{"$": {"src": "res/icon.png"}}];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// CONFIG: 접근허용 세팅
|
|
162
|
+
configXml["widget"]["access"] = [{"$": {"origin": "*"}}];
|
|
163
|
+
configXml["widget"]["allow-navigation"] = [{"$": {"href": "*"}}];
|
|
164
|
+
configXml["widget"]["allow-intent"] = [{"$": {"href": "*"}}];
|
|
165
|
+
configXml["widget"]["preference"] = [{"$": {"name": "MixedContentMode", "value": "0"}}];
|
|
166
|
+
|
|
167
|
+
// CONFIG: ANDROID usesCleartextTraffic 설정
|
|
168
|
+
if (this._opt.config.platform?.android) {
|
|
169
|
+
configXml.widget.$["xmlns:android"] = "http://schemas.android.com/apk/res/android";
|
|
170
|
+
|
|
171
|
+
configXml["widget"]["platform"] = configXml["widget"]["platform"] ?? [];
|
|
172
|
+
configXml["widget"]["platform"].push({
|
|
173
|
+
"$": {
|
|
174
|
+
"name": "android"
|
|
175
|
+
},
|
|
176
|
+
"edit-config": [{
|
|
177
|
+
"$": {
|
|
178
|
+
"file": "app/src/main/AndroidManifest.xml",
|
|
179
|
+
"mode": "merge",
|
|
180
|
+
"target": "/manifest/application"
|
|
181
|
+
},
|
|
182
|
+
"application": [{
|
|
183
|
+
"$": {
|
|
184
|
+
"android:usesCleartextTraffic": "true"
|
|
185
|
+
}
|
|
186
|
+
}]
|
|
187
|
+
}]
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// CONFIG: 파일 새로 쓰기
|
|
192
|
+
const configResultContent = new xml2js.Builder().buildObject(configXml);
|
|
193
|
+
await FsUtil.writeFileAsync(configFilePath, configResultContent);
|
|
194
|
+
|
|
195
|
+
// 각 플랫폼 www 준비
|
|
196
|
+
await this._execAsync(`${BIN_PATH} prepare`, this._opt.cordovaPath);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public async buildAsync(outPath: string): Promise<void> {
|
|
200
|
+
// 실행
|
|
201
|
+
const buildType = this._opt.config.debug ? "debug" : "release";
|
|
202
|
+
for (const platform of this._platforms) {
|
|
203
|
+
await this._execAsync(`${BIN_PATH} build ${platform} --${buildType}`, this._opt.cordovaPath);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 결과물 복사: ANDROID
|
|
207
|
+
if (this._opt.config.platform?.android) {
|
|
208
|
+
const targetOutPath = path.resolve(outPath, "android");
|
|
209
|
+
const apkFileName = this._opt.config.platform.android.sign ? `app-${buildType}.apk` : `app-${buildType}-unsigned.apk`;
|
|
210
|
+
const latestDistApkFileName = path.basename(`${this._opt.config.appName}${this._opt.config.platform.android.sign ? "" : "-unsigned"}-latest.apk`);
|
|
211
|
+
await FsUtil.mkdirsAsync(targetOutPath);
|
|
212
|
+
await FsUtil.copyAsync(
|
|
213
|
+
path.resolve(this._opt.cordovaPath, "platforms/android/app/build/outputs/apk", buildType, apkFileName),
|
|
214
|
+
path.resolve(targetOutPath, latestDistApkFileName)
|
|
215
|
+
);
|
|
216
|
+
// 자동업데이트를 위한 파일 쓰기
|
|
217
|
+
await FsUtil.copyAsync(
|
|
218
|
+
path.resolve(this._opt.cordovaPath, "platforms/android/app/build/outputs/apk", buildType, apkFileName),
|
|
219
|
+
path.resolve(path.resolve(targetOutPath, "updates"), this._npmConfig.version + ".apk")
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
public static async runWebviewOnDeviceAsync(opt: {
|
|
225
|
+
platform: string,
|
|
226
|
+
pkgName: string,
|
|
227
|
+
url?: string
|
|
228
|
+
}): Promise<void> {
|
|
229
|
+
const cordovaPath = path.resolve(process.cwd(), `packages/${opt.pkgName}/.cache/cordova/`);
|
|
230
|
+
|
|
231
|
+
if (opt.url !== undefined) {
|
|
232
|
+
await FsUtil.removeAsync(path.resolve(cordovaPath, "www"));
|
|
233
|
+
await FsUtil.mkdirsAsync(path.resolve(cordovaPath, "www"));
|
|
234
|
+
await FsUtil.writeFileAsync(path.resolve(cordovaPath, "www/index.html"), `'${opt.url}'로 이동중... <script>setTimeout(function () {window.location.href = "${opt.url.replace(/\/$/, "")}/${opt.pkgName}/cordova/"}, 3000);</script>`.trim());
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const binPath = path.resolve(process.cwd(), "node_modules/.bin/cordova.cmd");
|
|
238
|
+
await SdProcess.spawnAsync(`${binPath} run ${opt.platform} --device`, {cwd: cordovaPath}, true);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -17,12 +17,13 @@ import {
|
|
|
17
17
|
import nodeStdLibBrowser from "node-stdlib-browser";
|
|
18
18
|
import nodeStdLibBrowserPlugin from "node-stdlib-browser/helpers/esbuild/plugin";
|
|
19
19
|
import {ExecutionResult} from "@angular-devkit/build-angular/src/tools/esbuild/bundler-execution-result";
|
|
20
|
-
import {INpmConfig, ISdCliPackageBuildResult} from "../commons";
|
|
20
|
+
import {INpmConfig, ISdCliClientPackageConfig, ISdCliPackageBuildResult} from "../commons";
|
|
21
21
|
import {generateIndexHtml} from "@angular-devkit/build-angular/src/tools/esbuild/index-html-generator";
|
|
22
22
|
import {copyAssets} from "@angular-devkit/build-angular/src/utils/copy-assets";
|
|
23
23
|
import {extractLicenses} from "@angular-devkit/build-angular/src/tools/esbuild/license-extractor";
|
|
24
24
|
import {augmentAppWithServiceWorkerEsbuild} from "@angular-devkit/build-angular/src/utils/service-worker";
|
|
25
25
|
import {createGlobalStylesBundleOptions} from "@angular-devkit/build-angular/src/tools/esbuild/global-styles";
|
|
26
|
+
import {Entrypoint} from "@angular-devkit/build-angular/src/utils/index-file/augment-index-html";
|
|
26
27
|
|
|
27
28
|
export class SdNgBundler {
|
|
28
29
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdNgEsbuildBuilder"]);
|
|
@@ -34,8 +35,14 @@ export class SdNgBundler {
|
|
|
34
35
|
|
|
35
36
|
private readonly _outputCache = new Map<string, string | number>();
|
|
36
37
|
|
|
37
|
-
public constructor(
|
|
38
|
-
|
|
38
|
+
public constructor(opt: {
|
|
39
|
+
dev: boolean,
|
|
40
|
+
builderType: keyof ISdCliClientPackageConfig["builder"],
|
|
41
|
+
pkgPath: string,
|
|
42
|
+
cordovaPlatforms: string[] | undefined,
|
|
43
|
+
outputPath: string
|
|
44
|
+
}) {
|
|
45
|
+
this._options = this._getOptions(opt);
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
public removeCache(filePaths: string[]): void {
|
|
@@ -58,7 +65,7 @@ export class SdNgBundler {
|
|
|
58
65
|
|
|
59
66
|
const results = [
|
|
60
67
|
...bundlingResult.warnings.map((warn) => ({
|
|
61
|
-
filePath: warn.location?.file !== undefined ? path.resolve(this.
|
|
68
|
+
filePath: warn.location?.file !== undefined ? path.resolve(this._options.workspaceRoot, warn.location.file) : undefined,
|
|
62
69
|
line: warn.location?.line,
|
|
63
70
|
char: warn.location?.column,
|
|
64
71
|
code: undefined,
|
|
@@ -67,7 +74,7 @@ export class SdNgBundler {
|
|
|
67
74
|
type: "build" as const
|
|
68
75
|
})),
|
|
69
76
|
...bundlingResult.errors?.map((err) => ({
|
|
70
|
-
filePath: err.location?.file !== undefined ? path.resolve(this.
|
|
77
|
+
filePath: err.location?.file !== undefined ? path.resolve(this._options.workspaceRoot, err.location.file) : undefined,
|
|
71
78
|
line: err.location?.line,
|
|
72
79
|
char: err.location?.column !== undefined ? err.location.column + 1 : undefined,
|
|
73
80
|
code: undefined,
|
|
@@ -80,7 +87,7 @@ export class SdNgBundler {
|
|
|
80
87
|
...this._sourceFileCache.keys(),
|
|
81
88
|
...this._sourceFileCache.babelFileCache.keys()
|
|
82
89
|
].map((item) => path.resolve(item));
|
|
83
|
-
let affectedSourceFilePaths = watchFilePaths.filter((item) => PathUtil.isChildPath(item, this.
|
|
90
|
+
let affectedSourceFilePaths = watchFilePaths.filter((item) => PathUtil.isChildPath(item, this._options.workspaceRoot));
|
|
84
91
|
if (bundlingResult.errors) {
|
|
85
92
|
return {
|
|
86
93
|
filePaths: watchFilePaths,
|
|
@@ -92,8 +99,8 @@ export class SdNgBundler {
|
|
|
92
99
|
const depsMap = new Map<string, Set<string>>();
|
|
93
100
|
for (const entry of Object.entries(bundlingResult.metafile.inputs)) {
|
|
94
101
|
for (const imp of entry[1].imports) {
|
|
95
|
-
const deps = depsMap.getOrCreate(path.resolve(this.
|
|
96
|
-
deps.add(path.resolve(this.
|
|
102
|
+
const deps = depsMap.getOrCreate(path.resolve(this._options.workspaceRoot, imp.path), new Set<string>());
|
|
103
|
+
deps.add(path.resolve(this._options.workspaceRoot, entry[0]));
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
|
|
@@ -118,7 +125,7 @@ export class SdNgBundler {
|
|
|
118
125
|
affectedFilePathSet.add(path.resolve(modFile));
|
|
119
126
|
affectedFilePathSet.adds(...searchAffectedFiles(path.resolve(modFile)));
|
|
120
127
|
}
|
|
121
|
-
affectedSourceFilePaths = Array.from(affectedFilePathSet.values()).filter((item) => PathUtil.isChildPath(item, this.
|
|
128
|
+
affectedSourceFilePaths = Array.from(affectedFilePathSet.values()).filter((item) => PathUtil.isChildPath(item, this._options.workspaceRoot));
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
const executionResult = new ExecutionResult(this._contexts, this._sourceFileCache);
|
|
@@ -177,9 +184,8 @@ export class SdNgBundler {
|
|
|
177
184
|
|
|
178
185
|
//-- write
|
|
179
186
|
|
|
180
|
-
const distPath = path.resolve(this._options.outputPath, "dist", ...(this._opt.builderType === "web" ? [] : [this._opt.builderType]));
|
|
181
187
|
for (const outputFile of executionResult.outputFiles) {
|
|
182
|
-
const distFilePath = path.resolve(
|
|
188
|
+
const distFilePath = path.resolve(this._options.outputPath, outputFile.path);
|
|
183
189
|
|
|
184
190
|
const prev = this._outputCache.get(distFilePath);
|
|
185
191
|
if (prev !== Buffer.from(outputFile.contents).toString("base64")) {
|
|
@@ -191,7 +197,7 @@ export class SdNgBundler {
|
|
|
191
197
|
const prev = this._outputCache.get(assetFile.source);
|
|
192
198
|
const curr = FsUtil.lstat(assetFile.source).mtime.getTime();
|
|
193
199
|
if (prev !== curr) {
|
|
194
|
-
await FsUtil.copyAsync(assetFile.source, path.resolve(
|
|
200
|
+
await FsUtil.copyAsync(assetFile.source, path.resolve(this._options.outputPath, assetFile.destination));
|
|
195
201
|
this._outputCache.set(assetFile.source, curr);
|
|
196
202
|
}
|
|
197
203
|
}
|
|
@@ -277,7 +283,7 @@ export class SdNgBundler {
|
|
|
277
283
|
minifySyntax: !this._options.watch,
|
|
278
284
|
minifyWhitespace: !this._options.watch,
|
|
279
285
|
pure: ['forwardRef'],
|
|
280
|
-
outdir: this._options.
|
|
286
|
+
outdir: this._options.workspaceRoot,
|
|
281
287
|
outExtension: undefined,
|
|
282
288
|
sourcemap: this._options.watch,
|
|
283
289
|
splitting: true,
|
|
@@ -360,7 +366,13 @@ export class SdNgBundler {
|
|
|
360
366
|
};
|
|
361
367
|
}
|
|
362
368
|
|
|
363
|
-
private _getOptions(opt: {
|
|
369
|
+
private _getOptions(opt: {
|
|
370
|
+
dev: boolean,
|
|
371
|
+
builderType: keyof ISdCliClientPackageConfig["builder"],
|
|
372
|
+
pkgPath: string,
|
|
373
|
+
cordovaPlatforms: string[] | undefined,
|
|
374
|
+
outputPath: string,
|
|
375
|
+
}): NormalizedApplicationBuildOptions {
|
|
364
376
|
const mainFilePath = path.resolve(opt.pkgPath, "src/main.ts");
|
|
365
377
|
const tsconfigFilePath = path.resolve(opt.pkgPath, "tsconfig.json");
|
|
366
378
|
const indexHtmlFilePath = path.resolve(opt.pkgPath, "src/index.html");
|
|
@@ -400,20 +412,47 @@ export class SdNgBundler {
|
|
|
400
412
|
verbose: false,
|
|
401
413
|
watch: opt.dev,
|
|
402
414
|
workspaceRoot: opt.pkgPath,
|
|
403
|
-
entryPoints: {
|
|
415
|
+
entryPoints: {
|
|
416
|
+
main: mainFilePath,
|
|
417
|
+
...opt.builderType === "cordova" ? {
|
|
418
|
+
"cordova-entry": path.resolve(path.dirname(fileURLToPath(import.meta.url)), `../../lib/cordova-entry.js`)
|
|
419
|
+
} : {}
|
|
420
|
+
},
|
|
404
421
|
optimizationOptions: {
|
|
405
422
|
scripts: !opt.dev,
|
|
406
423
|
styles: {minify: !opt.dev, inlineCritical: !opt.dev},
|
|
407
424
|
fonts: {inline: !opt.dev}
|
|
408
425
|
},
|
|
409
|
-
outputPath: opt.
|
|
426
|
+
outputPath: opt.outputPath,
|
|
410
427
|
outExtension: undefined,
|
|
411
428
|
sourcemapOptions: {vendor: false, hidden: false, scripts: opt.dev, styles: opt.dev},
|
|
412
429
|
tsconfig: tsconfigFilePath,
|
|
413
430
|
projectRoot: opt.pkgPath,
|
|
414
431
|
assets: [
|
|
415
|
-
{
|
|
416
|
-
{
|
|
432
|
+
{input: 'src', glob: 'favicon.ico', output: ''},
|
|
433
|
+
{input: 'src\\assets', glob: '**/*', output: 'assets'},
|
|
434
|
+
...opt.dev && opt.cordovaPlatforms ? opt.cordovaPlatforms.mapMany((platform) => [
|
|
435
|
+
{
|
|
436
|
+
input: `.cache\\cordova\\platforms\\${platform}\\platform_www\\plugins`,
|
|
437
|
+
glob: '**/*',
|
|
438
|
+
output: `cordova-${platform}/plugins`
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
input: `.cache\\cordova\\platforms\\${platform}\\platform_www`,
|
|
442
|
+
glob: 'cordova.js',
|
|
443
|
+
output: `cordova-${platform}`
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
input: `.cache\\cordova\\platforms\\${platform}\\platform_www`,
|
|
447
|
+
glob: 'cordova_plugins.js',
|
|
448
|
+
output: `cordova-${platform}`
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
input: `.cache\\cordova\\platforms\\${platform}\\www`,
|
|
452
|
+
glob: 'config.xml',
|
|
453
|
+
output: `cordova-${platform}`
|
|
454
|
+
},
|
|
455
|
+
]) : []
|
|
417
456
|
],
|
|
418
457
|
outputNames: {bundles: '[name]', media: 'media/[name]'},
|
|
419
458
|
fileReplacements: undefined,
|
|
@@ -428,7 +467,10 @@ export class SdNgBundler {
|
|
|
428
467
|
['polyfills', true],
|
|
429
468
|
['styles', false],
|
|
430
469
|
['vendor', true],
|
|
431
|
-
['main', true]
|
|
470
|
+
['main', true],
|
|
471
|
+
...opt.builderType === "cordova" ? [
|
|
472
|
+
["cordova-entry", true] as Entrypoint
|
|
473
|
+
] : []
|
|
432
474
|
]
|
|
433
475
|
},
|
|
434
476
|
tailwindConfiguration: undefined
|
|
@@ -5,11 +5,14 @@ import {FunctionQueue, Wait} from "@simplysm/sd-core-common";
|
|
|
5
5
|
import path from "path";
|
|
6
6
|
import {SdNgBundler} from "../build-tools/SdNgBundler";
|
|
7
7
|
import {SdLinter} from "../build-tools/SdLinter";
|
|
8
|
+
import {SdCliCordova} from "../build-tools/SdCliCordova";
|
|
8
9
|
|
|
10
|
+
// TODO: ROUTER 자동생성
|
|
9
11
|
export class SdCliClientBuilder extends EventEmitter {
|
|
10
12
|
private readonly _logger = Logger.get(["simplysm", "sd-cli", "SdCliClientBuilder"]);
|
|
11
13
|
private readonly _pkgConf: ISdCliClientPackageConfig;
|
|
12
14
|
private _builders?: SdNgBundler[];
|
|
15
|
+
private _cordova?: SdCliCordova;
|
|
13
16
|
|
|
14
17
|
public constructor(private readonly _projConf: ISdCliConfig,
|
|
15
18
|
private readonly _pkgPath: string) {
|
|
@@ -71,12 +74,27 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
71
74
|
affectedFilePaths: string[];
|
|
72
75
|
buildResults: ISdCliPackageBuildResult[];
|
|
73
76
|
}> {
|
|
77
|
+
const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as (keyof ISdCliClientPackageConfig["builder"])[]);
|
|
78
|
+
if (this._pkgConf.builder?.cordova && !this._cordova) {
|
|
79
|
+
this._debug("CORDOVA 준비...");
|
|
80
|
+
this._cordova = new SdCliCordova({
|
|
81
|
+
pkgPath: this._pkgPath,
|
|
82
|
+
config: this._pkgConf.builder.cordova,
|
|
83
|
+
cordovaPath: path.resolve(this._pkgPath, ".cache/cordova")
|
|
84
|
+
});
|
|
85
|
+
await this._cordova.initializeAsync();
|
|
86
|
+
}
|
|
87
|
+
|
|
74
88
|
this._debug(`BUILD 준비...`);
|
|
75
|
-
const builderTypes = (Object.keys(this._pkgConf.builder ?? {web: {}}) as ("web")[]);
|
|
76
89
|
this._builders = this._builders ?? builderTypes.map((builderType) => new SdNgBundler({
|
|
77
90
|
dev: opt.dev,
|
|
78
91
|
builderType: builderType,
|
|
79
|
-
pkgPath: this._pkgPath
|
|
92
|
+
pkgPath: this._pkgPath,
|
|
93
|
+
cordovaPlatforms: builderType === "cordova" ? Object.keys(this._pkgConf.builder!.cordova!.platform ?? {browser: {}}) : undefined,
|
|
94
|
+
outputPath: builderType === "web" ? path.resolve(this._pkgPath, "dist")
|
|
95
|
+
: builderType === "electron" ? path.resolve(this._pkgPath, ".cache/electron/src")
|
|
96
|
+
: builderType === "cordova" && !opt.dev ? path.resolve(this._pkgPath, ".cache/cordova/www")
|
|
97
|
+
: path.resolve(this._pkgPath, "dist", builderType)
|
|
80
98
|
}));
|
|
81
99
|
|
|
82
100
|
this._debug(`BUILD & CHECK...`);
|
|
@@ -100,6 +118,11 @@ export class SdCliClientBuilder extends EventEmitter {
|
|
|
100
118
|
}
|
|
101
119
|
}
|
|
102
120
|
|
|
121
|
+
if (!opt.dev && this._cordova) {
|
|
122
|
+
this._debug("CORDOVA BUILD...");
|
|
123
|
+
await this._cordova.buildAsync(path.resolve(this._pkgPath, ".cache/cordova"));
|
|
124
|
+
}
|
|
125
|
+
|
|
103
126
|
const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {})
|
|
104
127
|
.mapMany((key) => FsUtil.glob(path.resolve(this._pkgPath, "../../node_modules", key)));
|
|
105
128
|
const watchFilePaths = filePaths
|
package/src/commons.ts
CHANGED
|
@@ -94,6 +94,7 @@ export interface ISdCliClientPackageConfig {
|
|
|
94
94
|
builder?: {
|
|
95
95
|
web?: ISdCliClientBuilderWebConfig;
|
|
96
96
|
electron?: ISdCliClientBuilderElectronConfig;
|
|
97
|
+
cordova?: ISdCliClientBuilderCordovaConfig;
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
@@ -126,3 +127,25 @@ export interface ISdCliClientBuilderWebConfig {
|
|
|
126
127
|
devServerPort?: number;
|
|
127
128
|
env?: Record<string, string>;
|
|
128
129
|
}
|
|
130
|
+
|
|
131
|
+
export interface ISdCliClientBuilderCordovaConfig {
|
|
132
|
+
appId: string;
|
|
133
|
+
appName: string;
|
|
134
|
+
plugins?: string[];
|
|
135
|
+
icon?: string;
|
|
136
|
+
debug?: boolean;
|
|
137
|
+
platform?: {
|
|
138
|
+
browser?: {};
|
|
139
|
+
android?: {
|
|
140
|
+
bundle?: boolean;
|
|
141
|
+
sign?: {
|
|
142
|
+
keystore: string;
|
|
143
|
+
storePassword: string;
|
|
144
|
+
alias: string;
|
|
145
|
+
password: string;
|
|
146
|
+
keystoreType: string;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
env?: Record<string, string>;
|
|
151
|
+
}
|
package/src/index.ts
CHANGED