@simplysm/sd-cli 12.5.21 → 12.5.23

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.
Files changed (195) hide show
  1. package/dist/{build-tools → entry}/SdCliCordova.d.ts +5 -6
  2. package/dist/{build-tools → entry}/SdCliCordova.js +117 -99
  3. package/dist/entry/SdCliCordova.js.map +1 -0
  4. package/dist/entry/SdCliElectron.d.ts +2 -2
  5. package/dist/entry/SdCliElectron.js +50 -40
  6. package/dist/entry/SdCliElectron.js.map +1 -1
  7. package/dist/entry/SdCliLocalUpdate.d.ts +1 -2
  8. package/dist/entry/SdCliLocalUpdate.js +26 -27
  9. package/dist/entry/SdCliLocalUpdate.js.map +1 -1
  10. package/dist/entry/SdCliProject.d.ts +1 -5
  11. package/dist/entry/SdCliProject.js +62 -288
  12. package/dist/entry/SdCliProject.js.map +1 -1
  13. package/dist/index.d.ts +23 -20
  14. package/dist/index.js +23 -20
  15. package/dist/index.js.map +1 -1
  16. package/dist/pkg-builders/SdMultiBuildRunner.d.ts +21 -0
  17. package/dist/pkg-builders/SdMultiBuildRunner.js +174 -0
  18. package/dist/pkg-builders/SdMultiBuildRunner.js.map +1 -0
  19. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.d.ts +4 -0
  20. package/dist/{build-tools → pkg-builders/client}/SdCliNgRoutesFileGenerator.js +7 -7
  21. package/dist/pkg-builders/client/SdCliNgRoutesFileGenerator.js.map +1 -0
  22. package/dist/pkg-builders/client/SdClientBuildRunner.d.ts +20 -0
  23. package/dist/pkg-builders/client/SdClientBuildRunner.js +135 -0
  24. package/dist/pkg-builders/client/SdClientBuildRunner.js.map +1 -0
  25. package/dist/pkg-builders/client/SdNgBundler.d.ts +29 -0
  26. package/dist/{build-tools → pkg-builders/client}/SdNgBundler.js +107 -151
  27. package/dist/pkg-builders/client/SdNgBundler.js.map +1 -0
  28. package/dist/{build-tools → pkg-builders/client}/SdNgBundlerContext.d.ts +1 -2
  29. package/dist/{build-tools → pkg-builders/client}/SdNgBundlerContext.js +19 -45
  30. package/dist/pkg-builders/client/SdNgBundlerContext.js.map +1 -0
  31. package/dist/pkg-builders/client/createSdNgPlugin.d.ts +10 -0
  32. package/dist/{bundle-plugins/sdNgPlugin.js → pkg-builders/client/createSdNgPlugin.js} +32 -33
  33. package/dist/pkg-builders/client/createSdNgPlugin.js.map +1 -0
  34. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.d.ts +5 -0
  35. package/dist/{build-tools → pkg-builders/lib}/SdCliIndexFileGenerator.js +11 -11
  36. package/dist/pkg-builders/lib/SdCliIndexFileGenerator.js.map +1 -0
  37. package/dist/pkg-builders/lib/SdJsLibBuildRunner.d.ts +16 -0
  38. package/dist/pkg-builders/lib/SdJsLibBuildRunner.js +81 -0
  39. package/dist/pkg-builders/lib/SdJsLibBuildRunner.js.map +1 -0
  40. package/dist/pkg-builders/lib/SdTsLibBuildRunner.d.ts +13 -0
  41. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js +89 -0
  42. package/dist/pkg-builders/lib/SdTsLibBuildRunner.js.map +1 -0
  43. package/dist/pkg-builders/lib/SdTsLibBuilder.d.ts +14 -0
  44. package/dist/pkg-builders/lib/SdTsLibBuilder.js +54 -0
  45. package/dist/pkg-builders/lib/SdTsLibBuilder.js.map +1 -0
  46. package/dist/pkg-builders/server/SdServerBuildRunner.d.ts +17 -0
  47. package/dist/{builders/SdCliServerBuilder.js → pkg-builders/server/SdServerBuildRunner.js} +48 -53
  48. package/dist/pkg-builders/server/SdServerBuildRunner.js.map +1 -0
  49. package/dist/pkg-builders/server/SdServerBundler.d.ts +19 -0
  50. package/dist/{build-tools → pkg-builders/server}/SdServerBundler.js +25 -30
  51. package/dist/pkg-builders/server/SdServerBundler.js.map +1 -0
  52. package/dist/pkg-builders/server/createSdServerPlugin.d.ts +10 -0
  53. package/dist/pkg-builders/server/createSdServerPlugin.js +53 -0
  54. package/dist/pkg-builders/server/createSdServerPlugin.js.map +1 -0
  55. package/dist/sd-cli.js +61 -54
  56. package/dist/sd-cli.js.map +1 -1
  57. package/dist/ts-builder/SdTsCompileWorker.d.ts +9 -0
  58. package/dist/ts-builder/SdTsCompileWorker.js +16 -0
  59. package/dist/ts-builder/SdTsCompileWorker.js.map +1 -0
  60. package/dist/ts-builder/SdTsCompiler.d.ts +7 -0
  61. package/dist/ts-builder/SdTsCompiler.js +557 -0
  62. package/dist/ts-builder/SdTsCompiler.js.map +1 -0
  63. package/dist/types/build-plugin.type.d.ts +14 -0
  64. package/dist/types/build-plugin.type.js +2 -0
  65. package/dist/types/build-plugin.type.js.map +1 -0
  66. package/dist/types/build.type.d.ts +15 -0
  67. package/dist/types/build.type.js +2 -0
  68. package/dist/types/build.type.js.map +1 -0
  69. package/dist/types/common-configs.type.d.ts +22 -0
  70. package/dist/types/common-configs.type.js +2 -0
  71. package/dist/types/common-configs.type.js.map +1 -0
  72. package/dist/types/sd-configs.type.d.ts +99 -0
  73. package/dist/types/sd-configs.type.js +2 -0
  74. package/dist/types/sd-configs.type.js.map +1 -0
  75. package/dist/types/ts-compiler.type.d.ts +29 -0
  76. package/dist/types/ts-compiler.type.js +2 -0
  77. package/dist/types/ts-compiler.type.js.map +1 -0
  78. package/dist/types/workers.type.d.ts +49 -0
  79. package/dist/types/workers.type.js +2 -0
  80. package/dist/types/workers.type.js.map +1 -0
  81. package/dist/utils/SdCliConvertMessageUtil.d.ts +21 -0
  82. package/dist/utils/SdCliConvertMessageUtil.js +137 -0
  83. package/dist/utils/SdCliConvertMessageUtil.js.map +1 -0
  84. package/dist/workers/compile-worker.js +27 -0
  85. package/dist/workers/compile-worker.js.map +1 -0
  86. package/dist/workers/lint-worker.js +36 -0
  87. package/dist/workers/lint-worker.js.map +1 -0
  88. package/dist/workers/server-worker.d.ts +1 -0
  89. package/dist/workers/server-worker.js +49 -0
  90. package/dist/workers/server-worker.js.map +1 -0
  91. package/package.json +8 -11
  92. package/src/entry/SdCliCordova.ts +363 -0
  93. package/src/entry/SdCliElectron.ts +96 -69
  94. package/src/entry/SdCliLocalUpdate.ts +43 -44
  95. package/src/entry/SdCliProject.ts +72 -417
  96. package/src/index.ts +23 -20
  97. package/src/pkg-builders/SdMultiBuildRunner.ts +250 -0
  98. package/src/{build-tools → pkg-builders/client}/SdCliNgRoutesFileGenerator.ts +7 -7
  99. package/src/pkg-builders/client/SdClientBuildRunner.ts +191 -0
  100. package/src/{build-tools → pkg-builders/client}/SdNgBundler.ts +135 -190
  101. package/src/pkg-builders/client/SdNgBundlerContext.ts +111 -0
  102. package/src/{bundle-plugins/sdNgPlugin.ts → pkg-builders/client/createSdNgPlugin.ts} +43 -46
  103. package/src/{build-tools → pkg-builders/lib}/SdCliIndexFileGenerator.ts +11 -11
  104. package/src/pkg-builders/lib/SdJsLibBuildRunner.ts +105 -0
  105. package/src/pkg-builders/lib/SdTsLibBuildRunner.ts +128 -0
  106. package/src/pkg-builders/lib/SdTsLibBuilder.ts +69 -0
  107. package/src/{builders/SdCliServerBuilder.ts → pkg-builders/server/SdServerBuildRunner.ts} +66 -78
  108. package/src/{build-tools → pkg-builders/server}/SdServerBundler.ts +40 -41
  109. package/src/pkg-builders/server/createSdServerPlugin.ts +77 -0
  110. package/src/sd-cli.ts +197 -211
  111. package/src/ts-builder/SdTsCompileWorker.ts +21 -0
  112. package/src/ts-builder/SdTsCompiler.ts +775 -0
  113. package/src/types/build-plugin.type.ts +16 -0
  114. package/src/types/build.type.ts +17 -0
  115. package/src/types/common-configs.type.ts +27 -0
  116. package/src/types/sd-configs.type.ts +114 -0
  117. package/src/types/ts-compiler.type.ts +29 -0
  118. package/src/types/workers.type.ts +27 -0
  119. package/src/utils/SdCliConvertMessageUtil.ts +177 -0
  120. package/src/workers/compile-worker.ts +31 -0
  121. package/src/workers/lint-worker.ts +44 -0
  122. package/src/workers/server-worker.ts +52 -0
  123. package/tsconfig.json +7 -1
  124. package/dist/build-cluster.js +0 -201
  125. package/dist/build-cluster.js.map +0 -1
  126. package/dist/build-tools/SdCliCordova.js.map +0 -1
  127. package/dist/build-tools/SdCliIndexFileGenerator.d.ts +0 -5
  128. package/dist/build-tools/SdCliIndexFileGenerator.js.map +0 -1
  129. package/dist/build-tools/SdCliNgRoutesFileGenerator.d.ts +0 -4
  130. package/dist/build-tools/SdCliNgRoutesFileGenerator.js.map +0 -1
  131. package/dist/build-tools/SdLinter.d.ts +0 -5
  132. package/dist/build-tools/SdLinter.js +0 -49
  133. package/dist/build-tools/SdLinter.js.map +0 -1
  134. package/dist/build-tools/SdNgBundler.d.ts +0 -29
  135. package/dist/build-tools/SdNgBundler.js.map +0 -1
  136. package/dist/build-tools/SdNgBundlerContext.js.map +0 -1
  137. package/dist/build-tools/SdReactBundler.d.ts +0 -25
  138. package/dist/build-tools/SdReactBundler.js +0 -295
  139. package/dist/build-tools/SdReactBundler.js.map +0 -1
  140. package/dist/build-tools/SdReactBundlerContext.d.ts +0 -14
  141. package/dist/build-tools/SdReactBundlerContext.js +0 -59
  142. package/dist/build-tools/SdReactBundlerContext.js.map +0 -1
  143. package/dist/build-tools/SdServerBundler.d.ts +0 -20
  144. package/dist/build-tools/SdServerBundler.js.map +0 -1
  145. package/dist/build-tools/SdTsCompiler.d.ts +0 -34
  146. package/dist/build-tools/SdTsCompiler.js +0 -534
  147. package/dist/build-tools/SdTsCompiler.js.map +0 -1
  148. package/dist/build-tools/SdTsLibBundler.d.ts +0 -13
  149. package/dist/build-tools/SdTsLibBundler.js +0 -58
  150. package/dist/build-tools/SdTsLibBundler.js.map +0 -1
  151. package/dist/builders/SdCliClientBuilder.d.ts +0 -18
  152. package/dist/builders/SdCliClientBuilder.js +0 -172
  153. package/dist/builders/SdCliClientBuilder.js.map +0 -1
  154. package/dist/builders/SdCliJsLibLinter.d.ts +0 -13
  155. package/dist/builders/SdCliJsLibLinter.js +0 -60
  156. package/dist/builders/SdCliJsLibLinter.js.map +0 -1
  157. package/dist/builders/SdCliServerBuilder.d.ts +0 -15
  158. package/dist/builders/SdCliServerBuilder.js.map +0 -1
  159. package/dist/builders/SdCliTsLibBuilder.d.ts +0 -12
  160. package/dist/builders/SdCliTsLibBuilder.js +0 -90
  161. package/dist/builders/SdCliTsLibBuilder.js.map +0 -1
  162. package/dist/bundle-plugins/sdNgPlugin.d.ts +0 -16
  163. package/dist/bundle-plugins/sdNgPlugin.js.map +0 -1
  164. package/dist/bundle-plugins/sdReactPlugin.d.ts +0 -16
  165. package/dist/bundle-plugins/sdReactPlugin.js +0 -117
  166. package/dist/bundle-plugins/sdReactPlugin.js.map +0 -1
  167. package/dist/bundle-plugins/sdServerPlugin.d.ts +0 -16
  168. package/dist/bundle-plugins/sdServerPlugin.js +0 -63
  169. package/dist/bundle-plugins/sdServerPlugin.js.map +0 -1
  170. package/dist/commons.d.ts +0 -145
  171. package/dist/commons.js +0 -2
  172. package/dist/commons.js.map +0 -1
  173. package/dist/server-worker.js +0 -57
  174. package/dist/server-worker.js.map +0 -1
  175. package/dist/utils/SdCliBuildResultUtil.d.ts +0 -16
  176. package/dist/utils/SdCliBuildResultUtil.js +0 -54
  177. package/dist/utils/SdCliBuildResultUtil.js.map +0 -1
  178. package/src/build-cluster.ts +0 -212
  179. package/src/build-tools/SdCliCordova.ts +0 -340
  180. package/src/build-tools/SdLinter.ts +0 -65
  181. package/src/build-tools/SdNgBundlerContext.ts +0 -137
  182. package/src/build-tools/SdReactBundler.ts +0 -372
  183. package/src/build-tools/SdReactBundlerContext.ts +0 -71
  184. package/src/build-tools/SdTsCompiler.ts +0 -754
  185. package/src/build-tools/SdTsLibBundler.ts +0 -72
  186. package/src/builders/SdCliClientBuilder.ts +0 -233
  187. package/src/builders/SdCliJsLibLinter.ts +0 -72
  188. package/src/builders/SdCliTsLibBuilder.ts +0 -126
  189. package/src/bundle-plugins/sdReactPlugin.ts +0 -164
  190. package/src/bundle-plugins/sdServerPlugin.ts +0 -94
  191. package/src/commons.ts +0 -171
  192. package/src/server-worker.ts +0 -65
  193. package/src/utils/SdCliBuildResultUtil.ts +0 -63
  194. /package/dist/{build-cluster.d.ts → workers/compile-worker.d.ts} +0 -0
  195. /package/dist/{server-worker.d.ts → workers/lint-worker.d.ts} +0 -0
@@ -0,0 +1,363 @@
1
+ import * as path from "path";
2
+ import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
3
+ import xml2js from "xml2js";
4
+ import JSZip from "jszip";
5
+ import { INpmConfig } from "../types/common-configs.type";
6
+ import { ISdClientBuilderCordovaConfig } from "../types/sd-configs.type";
7
+
8
+ const BIN_PATH = path.resolve(process.cwd(), "node_modules/.bin/cordova.cmd");
9
+
10
+ export class SdCliCordova {
11
+ private _logger = Logger.get(["simplysm", "sd-cli", "SdCliCordova"]);
12
+
13
+ private _platforms: string[];
14
+ private _npmConfig: INpmConfig;
15
+
16
+ constructor(private readonly _opt: { pkgPath: string; config: ISdClientBuilderCordovaConfig }) {
17
+ this._platforms = Object.keys(this._opt.config.platform ?? { browser: {} });
18
+ this._npmConfig = FsUtil.readJson(path.resolve(this._opt.pkgPath, "package.json"));
19
+ // this._logger = Logger.get(["simplysm", "sd-cli", this.constructor.name, this._npmConfig.name]);
20
+ }
21
+
22
+ private async _execAsync(cmd: string, cwd: string): Promise<void> {
23
+ this._logger.debug(cmd);
24
+ const msg = await SdProcess.spawnAsync(cmd, { cwd });
25
+ this._logger.debug(msg);
26
+ }
27
+
28
+ public async initializeAsync(): Promise<void> {
29
+ const cordovaPath = path.resolve(this._opt.pkgPath, ".cordova");
30
+
31
+ if (FsUtil.exists(cordovaPath)) {
32
+ this._logger.log("이미 생성되어있는 '.cordova'를 사용합니다.");
33
+ } else {
34
+ await this._execAsync(`${BIN_PATH} telemetry on`, this._opt.pkgPath);
35
+
36
+ // 프로젝트 생성
37
+ await this._execAsync(
38
+ `${BIN_PATH} create "${cordovaPath}" "${this._opt.config.appId}" "${this._opt.config.appName}"`,
39
+ process.cwd(),
40
+ );
41
+ }
42
+
43
+ // platforms 폴더 혹시 없으면 생성
44
+ FsUtil.mkdirs(path.resolve(cordovaPath, "platforms"));
45
+
46
+ // www 폴더 혹시 없으면 생성
47
+ FsUtil.mkdirs(path.resolve(cordovaPath, "www"));
48
+
49
+ // 미설치 빌드 플랫폼 신규 생성
50
+ const alreadyPlatforms = FsUtil.readdir(path.resolve(cordovaPath, "platforms"));
51
+ for (const platform of this._platforms) {
52
+ if (!alreadyPlatforms.includes(platform)) {
53
+ if (platform === "android") {
54
+ await this._execAsync(`${BIN_PATH} platform add ${platform}@12.0.0`, cordovaPath);
55
+ } else {
56
+ await this._execAsync(`${BIN_PATH} platform add ${platform}`, cordovaPath);
57
+ }
58
+ }
59
+ }
60
+
61
+ // 설치 미빌드 플랫폼 삭제
62
+ for (const alreadyPlatform of alreadyPlatforms) {
63
+ if (!this._platforms.includes(alreadyPlatform)) {
64
+ await this._execAsync(`${BIN_PATH} platform remove ${alreadyPlatform}`, cordovaPath);
65
+ }
66
+ }
67
+
68
+ // 설치된 미사용 플러그인 삭제
69
+ const pluginsFetch = FsUtil.exists(path.resolve(cordovaPath, "plugins/fetch.json"))
70
+ ? FsUtil.readJson(path.resolve(cordovaPath, "plugins/fetch.json"))
71
+ : undefined;
72
+ const alreadyPluginIds =
73
+ pluginsFetch != undefined
74
+ ? Object.keys(pluginsFetch)
75
+ : // Object.values(pluginsFetch).map((item: any) => item.source.id ?? item.source.url ?? item.source.path)
76
+ [];
77
+ const usePlugins = ["cordova-plugin-ionic-webview", ...(this._opt.config.plugins ?? [])].distinct();
78
+
79
+ for (const alreadyPluginId of alreadyPluginIds) {
80
+ let hasPlugin = false;
81
+ for (const usePlugin of usePlugins) {
82
+ if (alreadyPluginId === usePlugin) {
83
+ hasPlugin = true;
84
+ break;
85
+ }
86
+ /*if (
87
+ (usePlugin.includes("@") && alreadyPluginId === usePlugin) ||
88
+ (!usePlugin.includes("@") && alreadyPluginId.replace(/@.*$/, "") === usePlugin)
89
+ ) {
90
+ hasPlugin = true;
91
+ break;
92
+ }*/
93
+ }
94
+
95
+ if (!hasPlugin) {
96
+ await this._execAsync(`${BIN_PATH} plugin remove ${alreadyPluginId}`, cordovaPath);
97
+ }
98
+ }
99
+
100
+ // 미설치 플러그인들 설치
101
+ for (const usePlugin of usePlugins) {
102
+ if (
103
+ (usePlugin.includes("@") && !alreadyPluginIds.includes(usePlugin)) ||
104
+ (!usePlugin.includes("@") &&
105
+ !alreadyPluginIds.map((alreadyPluginId) => alreadyPluginId.replace(/@.*$/, "")).includes(usePlugin))
106
+ ) {
107
+ await this._execAsync(`${BIN_PATH} plugin add ${usePlugin}`, cordovaPath);
108
+ }
109
+ }
110
+
111
+ // ANDROID SIGN 파일 복사
112
+ if (this._opt.config.platform?.android?.sign) {
113
+ FsUtil.copy(
114
+ path.resolve(this._opt.pkgPath, this._opt.config.platform.android.sign.keystore),
115
+ path.resolve(cordovaPath, "android.keystore"),
116
+ );
117
+ } else {
118
+ FsUtil.remove(path.resolve(cordovaPath, "android.keystore"));
119
+ // SIGN을 안쓸경우 아래 파일이 생성되어 있으면 오류남
120
+ FsUtil.remove(path.resolve(cordovaPath, "platforms/android/release-signing.properties"));
121
+ }
122
+
123
+ // 빌드 옵션 파일 생성
124
+ FsUtil.writeJson(path.resolve(cordovaPath, "build.json"), {
125
+ ...(this._opt.config.platform?.android
126
+ ? {
127
+ android: {
128
+ release: {
129
+ packageType: this._opt.config.platform.android.bundle ? "bundle" : "apk",
130
+ ...(this._opt.config.platform.android.sign
131
+ ? {
132
+ keystore: path.resolve(cordovaPath, "android.keystore"),
133
+ storePassword: this._opt.config.platform.android.sign.storePassword,
134
+ alias: this._opt.config.platform.android.sign.alias,
135
+ password: this._opt.config.platform.android.sign.password,
136
+ keystoreType: this._opt.config.platform.android.sign.keystoreType,
137
+ }
138
+ : {}),
139
+ },
140
+ },
141
+ }
142
+ : {}),
143
+ });
144
+
145
+ // ICON 파일 복사
146
+ if (this._opt.config.icon != null) {
147
+ FsUtil.copy(
148
+ path.resolve(this._opt.pkgPath, this._opt.config.icon),
149
+ path.resolve(cordovaPath, "res/icons", path.basename(this._opt.config.icon)),
150
+ );
151
+ } else {
152
+ FsUtil.remove(path.resolve(cordovaPath, "res/icons"));
153
+ }
154
+
155
+ // SplashScreen 파일 생성
156
+ if (this._opt.config.platform?.android && this._opt.config.icon != null) {
157
+ FsUtil.writeFile(
158
+ path.resolve(cordovaPath, "res/screen/android/splashscreen.xml"),
159
+ `
160
+ <?xml version="1.0" encoding="utf-8"?>
161
+ <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
162
+ <item
163
+ android:width="48dp"
164
+ android:height="48dp"
165
+ android:drawable="@mipmap/ic_launcher"
166
+ android:gravity="center" />
167
+ </layer-list>`.trim(),
168
+ );
169
+ }
170
+
171
+ // CONFIG: 초기값 백업
172
+ const configFilePath = path.resolve(cordovaPath, "config.xml");
173
+ const configBackFilePath = path.resolve(cordovaPath, "config.xml.bak");
174
+ if (!FsUtil.exists(configBackFilePath)) {
175
+ FsUtil.copy(configFilePath, configBackFilePath);
176
+ }
177
+
178
+ // CONFIG: 초기값 읽기
179
+ const configFileContent = FsUtil.readFile(configBackFilePath);
180
+ const configXml = await xml2js.parseStringPromise(configFileContent);
181
+
182
+ // CONFIG: 버전 설정
183
+ configXml.widget.$.version = this._npmConfig.version;
184
+
185
+ // CONFIG: ICON 설정
186
+ if (this._opt.config.icon != null) {
187
+ configXml["widget"]["icon"] = [{ $: { src: "res/icons/" + path.basename(this._opt.config.icon) } }];
188
+ }
189
+
190
+ // CONFIG: 접근허용 세팅
191
+ configXml["widget"]["access"] = [{ $: { origin: "*" } }];
192
+ configXml["widget"]["allow-navigation"] = [{ $: { href: "*" } }];
193
+ configXml["widget"]["allow-intent"] = [{ $: { href: "*" } }];
194
+ configXml["widget"]["preference"] = [{ $: { name: "MixedContentMode", value: "0" } }];
195
+
196
+ // CONFIG: ANDROID usesCleartextTraffic 설정 및 splashscreen 파일 설정
197
+ if (this._opt.config.platform?.android) {
198
+ configXml.widget.$["xmlns:android"] = "http://schemas.android.com/apk/res/android";
199
+
200
+ configXml["widget"]["platform"] = configXml["widget"]["platform"] ?? [];
201
+
202
+ const androidPlatform = {
203
+ "$": {
204
+ name: "android",
205
+ },
206
+ "preference": [
207
+ {
208
+ $: {
209
+ name: "AndroidWindowSplashScreenAnimatedIcon",
210
+ value: "res/screen/android/splashscreen.xml",
211
+ },
212
+ },
213
+ ],
214
+ "edit-config": [
215
+ {
216
+ $: {
217
+ file: "app/src/main/AndroidManifest.xml",
218
+ mode: "merge",
219
+ target: "/manifest/application",
220
+ },
221
+ application: [
222
+ {
223
+ $: {
224
+ "android:usesCleartextTraffic": "true",
225
+ },
226
+ },
227
+ ],
228
+ },
229
+ ],
230
+ };
231
+
232
+ if (this._opt.config.platform.android.sdkVersion != null) {
233
+ androidPlatform.preference.push(
234
+ ...[
235
+ {
236
+ $: {
237
+ name: "android-maxSdkVersion",
238
+ value: `${this._opt.config.platform.android.sdkVersion}`,
239
+ },
240
+ },
241
+ {
242
+ $: {
243
+ name: "android-minSdkVersion",
244
+ value: `${this._opt.config.platform.android.sdkVersion}`,
245
+ },
246
+ },
247
+ {
248
+ $: {
249
+ name: "android-targetSdkVersion",
250
+ value: `${this._opt.config.platform.android.sdkVersion}`,
251
+ },
252
+ },
253
+ {
254
+ $: {
255
+ name: "android-compileSdkVersion",
256
+ value: `33`,
257
+ },
258
+ },
259
+ ],
260
+ );
261
+ }
262
+
263
+ if (this._opt.config.platform.android.permissions) {
264
+ androidPlatform["config-file"] = androidPlatform["config-file"] ?? [];
265
+ androidPlatform["config-file"].push({
266
+ "$": {
267
+ target: "AndroidManifest.xml",
268
+ parent: "/*",
269
+ },
270
+ "uses-permission": this._opt.config.platform.android.permissions.map((perm) => ({
271
+ $: {
272
+ "android:name": `android.permission.${perm.name}`,
273
+ ...(perm.maxSdkVersion != null
274
+ ? {
275
+ "android:maxSdkVersion": `${perm.maxSdkVersion}`,
276
+ }
277
+ : {}),
278
+ },
279
+ })),
280
+ });
281
+ }
282
+
283
+ configXml["widget"]["platform"].push(androidPlatform);
284
+ }
285
+
286
+ // CONFIG: 파일 새로 쓰기
287
+ const configResultContent = new xml2js.Builder().buildObject(configXml);
288
+ FsUtil.writeFile(configFilePath, configResultContent);
289
+
290
+ // 각 플랫폼 www 준비
291
+ await this._execAsync(`${BIN_PATH} prepare`, cordovaPath);
292
+ }
293
+
294
+ public async buildAsync(outPath: string): Promise<void> {
295
+ const cordovaPath = path.resolve(this._opt.pkgPath, ".cordova");
296
+
297
+ // 실행
298
+ const buildType = this._opt.config.debug ? "debug" : "release";
299
+ for (const platform of this._platforms) {
300
+ await this._execAsync(`${BIN_PATH} build ${platform} --${buildType}`, cordovaPath);
301
+ }
302
+
303
+ for (const platform of Object.keys(this._opt.config.platform ?? {})) {
304
+ const targetOutPath = path.resolve(outPath, platform);
305
+
306
+ // 결과물 복사: ANDROID
307
+ if (platform === "android") {
308
+ const apkFileName = this._opt.config.platform!.android!.sign
309
+ ? `app-${buildType}.apk`
310
+ : `app-${buildType}-unsigned.apk`;
311
+ const latestDistApkFileName = path.basename(
312
+ `${this._opt.config.appName}${this._opt.config.platform!.android!.sign ? "" : "-unsigned"}-latest.apk`,
313
+ );
314
+ FsUtil.mkdirs(targetOutPath);
315
+ FsUtil.copy(
316
+ path.resolve(cordovaPath, "platforms/android/app/build/outputs/apk", buildType, apkFileName),
317
+ path.resolve(targetOutPath, latestDistApkFileName),
318
+ );
319
+ }
320
+
321
+ // 자동업데이트를 위한 파일 쓰기 (ZIP)
322
+ const zip = new JSZip();
323
+ const wwwFiles = FsUtil.glob(path.resolve(cordovaPath, "www/**/*"), { nodir: true });
324
+ for (const wwwFile of wwwFiles) {
325
+ const relFilePath = path.relative(path.resolve(cordovaPath, "www"), wwwFile);
326
+ const fileBuffer = FsUtil.readFileBuffer(wwwFile);
327
+ zip.file(relFilePath, fileBuffer);
328
+ }
329
+ const platformWwwFiles = FsUtil.glob(path.resolve(cordovaPath, "platforms", platform, "platform_www/**/*"), {
330
+ nodir: true,
331
+ });
332
+ for (const platformWwwFile of platformWwwFiles) {
333
+ const relFilePath = path.relative(
334
+ path.resolve(cordovaPath, "platforms", platform, "platform_www"),
335
+ platformWwwFile,
336
+ );
337
+ const fileBuffer = FsUtil.readFileBuffer(platformWwwFile);
338
+ zip.file(relFilePath, fileBuffer);
339
+ }
340
+
341
+ FsUtil.writeFile(
342
+ path.resolve(path.resolve(outPath, platform, "updates"), this._npmConfig.version + ".zip"),
343
+ await zip.generateAsync({ type: "nodebuffer" }),
344
+ );
345
+ }
346
+ }
347
+
348
+ public static async runWebviewOnDeviceAsync(opt: { platform: string; pkgName: string; url?: string }): Promise<void> {
349
+ const cordovaPath = path.resolve(process.cwd(), `packages/${opt.pkgName}/.cordova/`);
350
+
351
+ if (opt.url !== undefined) {
352
+ FsUtil.remove(path.resolve(cordovaPath, "www"));
353
+ FsUtil.mkdirs(path.resolve(cordovaPath, "www"));
354
+ FsUtil.writeFile(
355
+ path.resolve(cordovaPath, "www/index.html"),
356
+ `'${opt.url}'로 이동중... <script>setTimeout(function () {window.location.href = "${opt.url.replace(/\/$/, "")}/${opt.pkgName}/cordova/"}, 3000);</script>`.trim(),
357
+ );
358
+ }
359
+
360
+ const binPath = path.resolve(process.cwd(), "node_modules/.bin/cordova.cmd");
361
+ await SdProcess.spawnAsync(`${binPath} run ${opt.platform} --device`, { cwd: cordovaPath }, true);
362
+ }
363
+ }
@@ -1,64 +1,69 @@
1
- import {FsUtil, Logger, SdProcess} from "@simplysm/sd-core-node";
2
- import {pathToFileURL} from "url";
1
+ import { FsUtil, Logger, SdProcess } from "@simplysm/sd-core-node";
2
+ import { pathToFileURL } from "url";
3
3
  import path from "path";
4
- import {INpmConfig, ISdCliClientBuilderElectronConfig, ISdCliConfig} from "../commons";
5
4
  import electronBuilder from "electron-builder";
5
+ import { ISdClientBuilderElectronConfig, ISdProjectConfig } from "../types/sd-configs.type";
6
+ import { INpmConfig } from "../types/common-configs.type";
6
7
 
7
8
  export class SdCliElectron {
8
- public static async runAsync(opt: {
9
- confFileRelPath: string;
10
- optNames: string[];
11
- pkgName: string;
12
- }): Promise<void> {
9
+ static async runAsync(opt: { confFileRelPath: string; optNames: string[]; pkgName: string }): Promise<void> {
13
10
  const logger = Logger.get(["simplysm", "sd-cli", "SdCliElectron", "runAsync"]);
14
11
 
15
12
  const pkgPath = path.resolve(process.cwd(), `packages/${opt.pkgName}`);
16
13
  const electronPath = path.resolve(pkgPath, "dist/electron");
17
14
 
18
15
  logger.log("설정 가져오기...");
19
- const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(true, opt.optNames) as ISdCliConfig;
16
+ const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(
17
+ true,
18
+ opt.optNames,
19
+ ) as ISdProjectConfig;
20
20
  const pkgConf = projConf.packages[opt.pkgName];
21
21
  if (pkgConf?.type !== "client" || pkgConf.builder?.electron === undefined) {
22
22
  throw new Error();
23
23
  }
24
24
 
25
25
  logger.log("package.json 파일 쓰기...");
26
- const npmConfig = (await FsUtil.readJsonAsync(path.resolve(pkgPath, `package.json`))) as INpmConfig;
26
+ const npmConfig = FsUtil.readJson(path.resolve(pkgPath, `package.json`)) as INpmConfig;
27
27
 
28
28
  const externalPkgNames = pkgConf.builder.electron.reinstallDependencies ?? [];
29
29
 
30
- await FsUtil.writeJsonAsync(path.resolve(electronPath, `package.json`), {
30
+ FsUtil.writeJson(path.resolve(electronPath, `package.json`), {
31
31
  name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
32
32
  version: npmConfig.version,
33
33
  description: npmConfig.description,
34
34
  main: "electron-main.js",
35
- ...pkgConf.builder.electron.postInstallScript !== undefined ? {
36
- scripts: {
37
- "postinstall": pkgConf.builder.electron.postInstallScript
38
- },
39
- } : {},
40
- dependencies: externalPkgNames.toObject((item) => item, (item) => npmConfig.dependencies![item])
35
+ ...(pkgConf.builder.electron.postInstallScript !== undefined
36
+ ? {
37
+ scripts: {
38
+ postinstall: pkgConf.builder.electron.postInstallScript,
39
+ },
40
+ }
41
+ : {}),
42
+ dependencies: externalPkgNames.toObject(
43
+ (item) => item,
44
+ (item) => npmConfig.dependencies![item],
45
+ ),
41
46
  });
42
47
 
43
48
  logger.log("npm install...");
44
- await SdProcess.spawnAsync(`npm install`, {cwd: electronPath}, true);
49
+ await SdProcess.spawnAsync(`npm install`, { cwd: electronPath }, true);
45
50
 
46
51
  for (const externalPkgName of externalPkgNames) {
47
52
  if (FsUtil.exists(path.resolve(electronPath, "node_modules", externalPkgName, "binding.gyp"))) {
48
53
  logger.log(`electron rebuild (${externalPkgName})...`);
49
- await SdProcess.spawnAsync(`electron-rebuild -m ./node_modules/${externalPkgName}`, {cwd: electronPath}, true);
54
+ await SdProcess.spawnAsync(
55
+ `electron-rebuild -m ./node_modules/${externalPkgName}`,
56
+ { cwd: electronPath },
57
+ true,
58
+ );
50
59
  }
51
60
  }
52
61
 
53
62
  logger.log("electron...");
54
- await SdProcess.spawnAsync(`electron .`, {cwd: electronPath}, true);
63
+ await SdProcess.spawnAsync(`electron .`, { cwd: electronPath }, true);
55
64
  }
56
65
 
57
- public static async buildForDevAsync(opt: {
58
- confFileRelPath: string;
59
- optNames: string[];
60
- pkgName: string;
61
- }): Promise<void> {
66
+ static async buildForDevAsync(opt: { confFileRelPath: string; optNames: string[]; pkgName: string }): Promise<void> {
62
67
  const logger = Logger.get(["simplysm", "sd-cli", "SdCliElectron", "buildForDevAsync"]);
63
68
 
64
69
  const pkgPath = path.resolve(process.cwd(), `packages/${opt.pkgName}`);
@@ -66,37 +71,49 @@ export class SdCliElectron {
66
71
  const electronDistPath = path.resolve(pkgPath, ".electron/dist");
67
72
 
68
73
  logger.log("설정 가져오기...");
69
- const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(true, opt.optNames) as ISdCliConfig;
74
+ const projConf = (await import(pathToFileURL(path.resolve(process.cwd(), opt.confFileRelPath)).href)).default(
75
+ true,
76
+ opt.optNames,
77
+ ) as ISdProjectConfig;
70
78
  const pkgConf = projConf.packages[opt.pkgName];
71
79
  if (pkgConf?.type !== "client" || pkgConf.builder?.electron === undefined) {
72
80
  throw new Error();
73
81
  }
74
82
 
75
83
  logger.log("package.json 파일 쓰기...");
76
- const npmConfig = (await FsUtil.readJsonAsync(path.resolve(pkgPath, `package.json`))) as INpmConfig;
84
+ const npmConfig = FsUtil.readJson(path.resolve(pkgPath, `package.json`)) as INpmConfig;
77
85
 
78
86
  const externalPkgNames = pkgConf.builder.electron.reinstallDependencies ?? [];
79
87
 
80
- await FsUtil.writeJsonAsync(path.resolve(electronPath, `package.json`), {
88
+ FsUtil.writeJson(path.resolve(electronPath, `package.json`), {
81
89
  name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
82
90
  version: npmConfig.version,
83
91
  description: npmConfig.description,
84
92
  main: "electron-main.js",
85
- ...pkgConf.builder.electron.postInstallScript !== undefined ? {
86
- scripts: {
87
- "postinstall": pkgConf.builder.electron.postInstallScript
88
- },
89
- } : {},
90
- dependencies: externalPkgNames.toObject((item) => item, (item) => npmConfig.dependencies![item])
93
+ ...(pkgConf.builder.electron.postInstallScript !== undefined
94
+ ? {
95
+ scripts: {
96
+ postinstall: pkgConf.builder.electron.postInstallScript,
97
+ },
98
+ }
99
+ : {}),
100
+ dependencies: externalPkgNames.toObject(
101
+ (item) => item,
102
+ (item) => npmConfig.dependencies![item],
103
+ ),
91
104
  });
92
105
 
93
106
  logger.log("npm install...");
94
- await SdProcess.spawnAsync(`npm install`, {cwd: electronPath}, true);
107
+ await SdProcess.spawnAsync(`npm install`, { cwd: electronPath }, true);
95
108
 
96
109
  for (const externalPkgName of externalPkgNames) {
97
110
  if (FsUtil.exists(path.resolve(electronPath, "node_modules", externalPkgName, "binding.gyp"))) {
98
111
  logger.log(`electron rebuild (${externalPkgName})...`);
99
- await SdProcess.spawnAsync(`electron-rebuild -m ./node_modules/${externalPkgName}`, {cwd: electronPath}, true);
112
+ await SdProcess.spawnAsync(
113
+ `electron-rebuild -m ./node_modules/${externalPkgName}`,
114
+ { cwd: electronPath },
115
+ true,
116
+ );
100
117
  }
101
118
  }
102
119
 
@@ -109,60 +126,68 @@ export class SdCliElectron {
109
126
  productName: npmConfig.description,
110
127
  asar: false,
111
128
  win: {
112
- target: "nsis"
129
+ target: "nsis",
113
130
  },
114
131
  nsis: {},
115
132
  directories: {
116
133
  app: electronPath,
117
- output: electronDistPath
134
+ output: electronDistPath,
118
135
  },
119
- ...pkgConf.builder.electron.installerIcon !== undefined ? {
120
- icon: path.resolve(pkgPath, "src", pkgConf.builder.electron.installerIcon)
121
- } : {},
122
- removePackageScripts: false
123
- }
136
+ ...(pkgConf.builder.electron.installerIcon !== undefined
137
+ ? {
138
+ icon: path.resolve(pkgPath, "src", pkgConf.builder.electron.installerIcon),
139
+ }
140
+ : {}),
141
+ removePackageScripts: false,
142
+ },
124
143
  });
125
144
 
126
- await FsUtil.copyAsync(
145
+ FsUtil.copy(
127
146
  path.resolve(electronDistPath, `${npmConfig.description} Setup ${npmConfig.version}.exe`),
128
- path.resolve(pkgPath, `dist/electron/${npmConfig.description}-dev.exe`)
147
+ path.resolve(pkgPath, `dist/electron/${npmConfig.description}-dev.exe`),
129
148
  );
130
149
  }
131
150
 
132
- public static async buildAsync(opt: {
133
- pkgPath: string;
134
- config: ISdCliClientBuilderElectronConfig;
135
- }): Promise<void> {
151
+ static async buildAsync(opt: { pkgPath: string; config: ISdClientBuilderElectronConfig }): Promise<void> {
136
152
  const logger = Logger.get(["simplysm", "sd-cli", "SdCliElectron", "buildAsync"]);
137
153
 
138
154
  const electronSrcPath = path.resolve(opt.pkgPath, ".electron/src");
139
155
  const electronDistPath = path.resolve(opt.pkgPath, ".electron/dist");
140
156
 
141
157
  logger.log("package.json 파일 쓰기...");
142
- const npmConfig = (await FsUtil.readJsonAsync(path.resolve(opt.pkgPath, `package.json`))) as INpmConfig;
158
+ const npmConfig = FsUtil.readJson(path.resolve(opt.pkgPath, `package.json`)) as INpmConfig;
143
159
 
144
160
  const externalPkgNames = opt.config.reinstallDependencies ?? [];
145
161
 
146
- await FsUtil.writeJsonAsync(path.resolve(electronSrcPath, `package.json`), {
162
+ FsUtil.writeJson(path.resolve(electronSrcPath, `package.json`), {
147
163
  name: npmConfig.name.replace(/^@/, "").replace(/\//, "-"),
148
164
  version: npmConfig.version,
149
165
  description: npmConfig.description,
150
166
  main: "electron-main.js",
151
- ...opt.config.postInstallScript !== undefined ? {
152
- scripts: {
153
- "postinstall": opt.config.postInstallScript
154
- },
155
- } : {},
156
- dependencies: externalPkgNames.toObject((item) => item, (item) => npmConfig.dependencies![item])
167
+ ...(opt.config.postInstallScript !== undefined
168
+ ? {
169
+ scripts: {
170
+ postinstall: opt.config.postInstallScript,
171
+ },
172
+ }
173
+ : {}),
174
+ dependencies: externalPkgNames.toObject(
175
+ (item) => item,
176
+ (item) => npmConfig.dependencies![item],
177
+ ),
157
178
  });
158
179
 
159
180
  logger.log("npm install...");
160
- await SdProcess.spawnAsync(`npm install`, {cwd: electronSrcPath}, true);
181
+ await SdProcess.spawnAsync(`npm install`, { cwd: electronSrcPath }, true);
161
182
 
162
183
  for (const externalPkgName of externalPkgNames) {
163
184
  if (FsUtil.exists(path.resolve(electronSrcPath, "node_modules", externalPkgName, "binding.gyp"))) {
164
185
  logger.log(`electron rebuild (${externalPkgName})...`);
165
- await SdProcess.spawnAsync(`electron-rebuild -m ./node_modules/${externalPkgName}`, {cwd: electronSrcPath}, true);
186
+ await SdProcess.spawnAsync(
187
+ `electron-rebuild -m ./node_modules/${externalPkgName}`,
188
+ { cwd: electronSrcPath },
189
+ true,
190
+ );
166
191
  }
167
192
  }
168
193
 
@@ -175,23 +200,25 @@ export class SdCliElectron {
175
200
  productName: npmConfig.description,
176
201
  asar: false,
177
202
  win: {
178
- target: "nsis"
203
+ target: "nsis",
179
204
  },
180
205
  nsis: {},
181
206
  directories: {
182
207
  app: electronSrcPath,
183
- output: electronDistPath
208
+ output: electronDistPath,
184
209
  },
185
- ...opt.config.installerIcon !== undefined ? {
186
- icon: path.resolve(opt.pkgPath, "src", opt.config.installerIcon)
187
- } : {},
188
- removePackageScripts: false
189
- }
210
+ ...(opt.config.installerIcon !== undefined
211
+ ? {
212
+ icon: path.resolve(opt.pkgPath, "src", opt.config.installerIcon),
213
+ }
214
+ : {}),
215
+ removePackageScripts: false,
216
+ },
190
217
  });
191
218
 
192
- await FsUtil.copyAsync(
219
+ FsUtil.copy(
193
220
  path.resolve(electronDistPath, `${npmConfig.description} Setup ${npmConfig.version}.exe`),
194
- path.resolve(opt.pkgPath, `dist/electron/${npmConfig.description}-latest.exe`)
221
+ path.resolve(opt.pkgPath, `dist/electron/${npmConfig.description}-latest.exe`),
195
222
  );
196
223
  }
197
- }
224
+ }