@arkts/image-manager 0.4.3 → 0.5.1
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/README.md +1 -75
- package/dist/default-emulator-config.d.cts +274 -3
- package/dist/default-emulator-config.d.mts +274 -3
- package/dist/default-product-config.cjs +8 -0
- package/dist/default-product-config.d.cts +379 -3
- package/dist/default-product-config.d.mts +379 -3
- package/dist/default-product-config.mjs +8 -0
- package/dist/index.cjs +1383 -1063
- package/dist/index.d.cts +1113 -537
- package/dist/index.d.mts +1112 -536
- package/dist/index.mjs +1307 -1034
- package/package.json +7 -2
- package/dist/emulator-config-DbI3FRE5.d.mts +0 -64
- package/dist/emulator-config-HeXlMqZ-.d.cts +0 -64
- package/dist/product-config-ByDVg0-5.d.mts +0 -67
- package/dist/product-config-DuzOJEvZ.d.cts +0 -67
- package/dist/types-CayFonNb.d.cts +0 -16
- package/dist/types-DD8_iqBV.d.mts +0 -16
package/dist/index.mjs
CHANGED
|
@@ -1,1288 +1,1561 @@
|
|
|
1
|
-
import axios, { AxiosError } from "axios";
|
|
2
|
-
import satisfies from "semver/functions/satisfies";
|
|
3
1
|
import INI from "ini";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
2
|
+
import { fromByteArray } from "base64-js";
|
|
3
|
+
import { RelativePattern, WriteableFlags, createNodeFileSystem } from "vscode-fs";
|
|
6
4
|
|
|
7
5
|
//#region package.json
|
|
8
|
-
var version = "0.
|
|
6
|
+
var version = "0.5.1";
|
|
9
7
|
|
|
10
8
|
//#endregion
|
|
11
|
-
//#region src/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
DevModel["PHEMU_FD02"] = "PHEMU-FD02";
|
|
17
|
-
DevModel["PHEMU_FD06"] = "PHEMU-FD06";
|
|
18
|
-
DevModel["PCEMU_FD00"] = "PCEMU-FD00";
|
|
19
|
-
DevModel["PCEMU_FD05"] = "PCEMU-FD05";
|
|
20
|
-
return DevModel;
|
|
21
|
-
}({});
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
//#region src/emulator-config.ts
|
|
25
|
-
let BaseEmulatorConfigItem;
|
|
26
|
-
(function(_BaseEmulatorConfigItem) {
|
|
27
|
-
function is(value) {
|
|
28
|
-
return typeof value === "object" && value !== null && "name" in value && typeof value.name === "string" && "deviceType" in value && typeof value.deviceType === "string" && "api" in value && typeof value.api === "number";
|
|
29
|
-
}
|
|
30
|
-
_BaseEmulatorConfigItem.is = is;
|
|
31
|
-
})(BaseEmulatorConfigItem || (BaseEmulatorConfigItem = {}));
|
|
32
|
-
let ParentEmulatorConfigItem;
|
|
33
|
-
(function(_ParentEmulatorConfigItem) {
|
|
34
|
-
function is(value) {
|
|
35
|
-
return BaseEmulatorConfigItem.is(value) && "resolutionWidth" in value && typeof value.resolutionWidth === "number" && "resolutionHeight" in value && typeof value.resolutionHeight === "number" && "physicalWidth" in value && typeof value.physicalWidth === "number" && "physicalHeight" in value && typeof value.physicalHeight === "number" && "diagonalSize" in value && typeof value.diagonalSize === "number" && "density" in value && typeof value.density === "number" && "memoryRamSize" in value && typeof value.memoryRamSize === "number" && "datadiskSize" in value && typeof value.datadiskSize === "number" && "procNumber" in value && typeof value.procNumber === "number" && "api" in value && typeof value.api === "number";
|
|
36
|
-
}
|
|
37
|
-
_ParentEmulatorConfigItem.is = is;
|
|
38
|
-
})(ParentEmulatorConfigItem || (ParentEmulatorConfigItem = {}));
|
|
39
|
-
let PhoneAllEmulatorConfigItem;
|
|
40
|
-
(function(_PhoneAllEmulatorConfigItem) {
|
|
41
|
-
function is(value) {
|
|
42
|
-
return ParentEmulatorConfigItem.is(value);
|
|
9
|
+
//#region src/common/serializable-content.ts
|
|
10
|
+
var SerializableContentImpl = class {
|
|
11
|
+
constructor(imageManager, content) {
|
|
12
|
+
this.imageManager = imageManager;
|
|
13
|
+
this.content = content;
|
|
43
14
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let GroupPhoneAllEmulatorConfigItem;
|
|
47
|
-
(function(_GroupPhoneAllEmulatorConfigItem) {
|
|
48
|
-
function is(value) {
|
|
49
|
-
return BaseEmulatorConfigItem.is(value) && "children" in value && Array.isArray(value.children) && value.children.every(PhoneAllEmulatorConfigItem.is);
|
|
15
|
+
getImageManager() {
|
|
16
|
+
return this.imageManager;
|
|
50
17
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
let PCAllEmulatorConfigItem;
|
|
54
|
-
(function(_PCAllEmulatorConfigItem) {
|
|
55
|
-
function is(value) {
|
|
56
|
-
return ParentEmulatorConfigItem.is(value);
|
|
18
|
+
getContent() {
|
|
19
|
+
return this.content;
|
|
57
20
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
(
|
|
62
|
-
|
|
63
|
-
return BaseEmulatorConfigItem.is(value) && "children" in value && Array.isArray(value.children) && value.children.every(PCAllEmulatorConfigItem.is);
|
|
21
|
+
toJSON() {
|
|
22
|
+
return {
|
|
23
|
+
imageManager: this.getImageManager().toJSON(),
|
|
24
|
+
content: this.getContent()
|
|
25
|
+
};
|
|
64
26
|
}
|
|
65
|
-
|
|
66
|
-
})(GroupPCAllEmulatorConfigItem || (GroupPCAllEmulatorConfigItem = {}));
|
|
27
|
+
};
|
|
67
28
|
|
|
68
29
|
//#endregion
|
|
69
|
-
//#region src/
|
|
70
|
-
var
|
|
71
|
-
constructor(
|
|
72
|
-
super(
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
75
|
-
|
|
30
|
+
//#region src/common/serializable-file.ts
|
|
31
|
+
var SerializableFileImpl = class extends SerializableContentImpl {
|
|
32
|
+
constructor(imageManager, content) {
|
|
33
|
+
super(imageManager, content);
|
|
34
|
+
this.imageManager = imageManager;
|
|
35
|
+
this.content = content;
|
|
36
|
+
}
|
|
37
|
+
getImageManager() {
|
|
38
|
+
return this.imageManager;
|
|
76
39
|
}
|
|
77
|
-
|
|
78
|
-
|
|
40
|
+
async writeToFileSystem(uri) {
|
|
41
|
+
const { adapter: { fs, dirname } } = this.imageManager.getOptions();
|
|
42
|
+
const directoryUri = dirname(uri);
|
|
43
|
+
if (!await fs.exists(directoryUri)) await fs.createDirectory(directoryUri);
|
|
44
|
+
const serializedContent = await this.serialize();
|
|
45
|
+
const encodedContent = new TextEncoder().encode(serializedContent);
|
|
46
|
+
await fs.writeFile(uri, encodedContent);
|
|
47
|
+
}
|
|
48
|
+
toJSON() {
|
|
49
|
+
return {
|
|
50
|
+
imageManager: this.getImageManager().toJSON(),
|
|
51
|
+
content: this.getContent()
|
|
52
|
+
};
|
|
79
53
|
}
|
|
80
54
|
};
|
|
81
|
-
(function(_DeployError) {
|
|
82
|
-
_DeployError.Code = /* @__PURE__ */ function(Code) {
|
|
83
|
-
Code["DEVICE_ALREADY_DEPLOYED"] = "DEVICE_ALREADY_DEPLOYED";
|
|
84
|
-
Code["LIST_JSON_NOT_AN_ARRAY"] = "LIST_JSON_NOT_AN_ARRAY";
|
|
85
|
-
Code["CATCHED_ERROR"] = "CATCHED_ERROR";
|
|
86
|
-
Code["MAYBE_OPENED_DEVICE_MANAGER_IN_DEVECO_STUDIO"] = "MAYBE_OPENED_DEVICE_MANAGER_IN_DEVECO_STUDIO";
|
|
87
|
-
Code["SYMLINK_SDK_PATH_EXISTS"] = "SYMLINK_SDK_PATH_EXISTS";
|
|
88
|
-
return Code;
|
|
89
|
-
}({});
|
|
90
|
-
})(DeployError || (DeployError = {}));
|
|
91
55
|
|
|
92
56
|
//#endregion
|
|
93
|
-
//#region src/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
57
|
+
//#region src/configs/config-ini/config-ini.ts
|
|
58
|
+
let ConfigIniFile;
|
|
59
|
+
(function(_ConfigIniFile) {
|
|
60
|
+
function is(value) {
|
|
61
|
+
return value instanceof ConfigIniFileImpl;
|
|
62
|
+
}
|
|
63
|
+
_ConfigIniFile.is = is;
|
|
64
|
+
})(ConfigIniFile || (ConfigIniFile = {}));
|
|
65
|
+
var ConfigIniFileImpl = class extends SerializableFileImpl {
|
|
66
|
+
constructor(device, configIniFilePath, content) {
|
|
67
|
+
super(device.getImageManager(), content);
|
|
68
|
+
this.device = device;
|
|
69
|
+
this.configIniFilePath = configIniFilePath;
|
|
70
|
+
this.content = content;
|
|
71
|
+
}
|
|
72
|
+
getDevice() {
|
|
73
|
+
return this.device;
|
|
74
|
+
}
|
|
75
|
+
static getFileUri(device) {
|
|
76
|
+
const { deployedPath, adapter: { join } } = device.getImageManager().getOptions();
|
|
77
|
+
return join(deployedPath, device.getListsFileItem().getContent().name, "config.ini");
|
|
78
|
+
}
|
|
79
|
+
static async safeReadAndParse(device) {
|
|
80
|
+
const { adapter: { fs } } = device.getImageManager().getOptions();
|
|
81
|
+
try {
|
|
82
|
+
const configIniFileContent = await fs.readFile(this.getFileUri(device)).then((buffer) => buffer.toString(), () => void 0);
|
|
83
|
+
if (!configIniFileContent?.length) return;
|
|
84
|
+
return INI.parse(configIniFileContent);
|
|
85
|
+
} catch {}
|
|
86
|
+
}
|
|
87
|
+
getFileUri() {
|
|
88
|
+
return this.configIniFilePath;
|
|
89
|
+
}
|
|
90
|
+
async serialize() {
|
|
91
|
+
return INI.stringify(Object.fromEntries(Object.entries(this.getContent()).filter(([key, value]) => {
|
|
92
|
+
return value !== void 0 && key.length > 0;
|
|
93
|
+
})));
|
|
94
|
+
}
|
|
95
|
+
async write() {
|
|
96
|
+
return this.writeToFileSystem(this.getFileUri());
|
|
97
|
+
}
|
|
98
|
+
toJSON() {
|
|
99
|
+
return {
|
|
100
|
+
...super.toJSON(),
|
|
101
|
+
fileUri: this.getFileUri().toJSON()
|
|
102
|
+
};
|
|
100
103
|
}
|
|
101
104
|
};
|
|
102
105
|
|
|
103
106
|
//#endregion
|
|
104
|
-
//#region src/
|
|
105
|
-
let
|
|
106
|
-
(function(
|
|
107
|
+
//#region src/configs/emulator/emulator-basic-item.ts
|
|
108
|
+
let EmulatorBasicItem;
|
|
109
|
+
(function(_EmulatorBasicItem) {
|
|
107
110
|
function is(value) {
|
|
108
|
-
return
|
|
111
|
+
return value instanceof EmulatorBasicItemImpl;
|
|
109
112
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//#endregion
|
|
114
|
-
//#region src/types.ts
|
|
115
|
-
function isPhoneAllSnakecaseDeviceType(value) {
|
|
116
|
-
return value === "phone" || value === "triplefold" || value === "widefold" || value === "foldable";
|
|
117
|
-
}
|
|
118
|
-
function isPCAllSnakecaseDeviceType(value) {
|
|
119
|
-
return value === "2in1_foldable" || value === "2in1";
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
//#endregion
|
|
123
|
-
//#region src/screens/base-screen.ts
|
|
124
|
-
var BaseScreenImpl = class {
|
|
125
|
-
constructor(options) {
|
|
126
|
-
this.options = options;
|
|
113
|
+
_EmulatorBasicItem.is = is;
|
|
114
|
+
function isDeviceType(value) {
|
|
115
|
+
return value === "2in1" || value === "tablet" || value === "tv" || value === "wearable" || value === "phone";
|
|
127
116
|
}
|
|
128
|
-
|
|
129
|
-
|
|
117
|
+
_EmulatorBasicItem.isDeviceType = isDeviceType;
|
|
118
|
+
function isContent(value) {
|
|
119
|
+
return typeof value === "object" && value !== null && "name" in value && "deviceType" in value && isDeviceType(value.deviceType);
|
|
130
120
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
_EmulatorBasicItem.isContent = isContent;
|
|
122
|
+
})(EmulatorBasicItem || (EmulatorBasicItem = {}));
|
|
123
|
+
var EmulatorBasicItemImpl = class extends SerializableContentImpl {
|
|
124
|
+
constructor(emulatorFile, content) {
|
|
125
|
+
super(emulatorFile.getImageManager(), content);
|
|
126
|
+
this.emulatorFile = emulatorFile;
|
|
127
|
+
this.content = content;
|
|
134
128
|
}
|
|
135
|
-
|
|
136
|
-
return this.
|
|
129
|
+
getEmulatorFile() {
|
|
130
|
+
return this.emulatorFile;
|
|
137
131
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
//#endregion
|
|
135
|
+
//#region src/configs/emulator/emulator-fold-item.ts
|
|
136
|
+
let EmulatorFoldItem;
|
|
137
|
+
(function(_EmulatorFoldItem) {
|
|
138
|
+
function is(value) {
|
|
139
|
+
return value instanceof EmulatorFoldItemImpl;
|
|
141
140
|
}
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
_EmulatorFoldItem.is = is;
|
|
142
|
+
function isDeviceType(value) {
|
|
143
|
+
return value === "foldable" || value === "2in1_foldable" || value === "triplefold" || value === "widefold";
|
|
144
144
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return
|
|
145
|
+
_EmulatorFoldItem.isDeviceType = isDeviceType;
|
|
146
|
+
function isContent(value) {
|
|
147
|
+
return typeof value === "object" && value !== null && "name" in value && "deviceType" in value && isDeviceType(value.deviceType);
|
|
148
148
|
}
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
_EmulatorFoldItem.isContent = isContent;
|
|
150
|
+
})(EmulatorFoldItem || (EmulatorFoldItem = {}));
|
|
151
|
+
var EmulatorFoldItemImpl = class extends SerializableContentImpl {
|
|
152
|
+
constructor(emulatorFile, content) {
|
|
153
|
+
super(emulatorFile.getImageManager(), content);
|
|
154
|
+
this.emulatorFile = emulatorFile;
|
|
155
|
+
this.content = content;
|
|
156
|
+
}
|
|
157
|
+
getEmulatorFile() {
|
|
158
|
+
return this.emulatorFile;
|
|
151
159
|
}
|
|
152
160
|
};
|
|
153
161
|
|
|
154
162
|
//#endregion
|
|
155
|
-
//#region src/
|
|
156
|
-
let
|
|
157
|
-
(function(
|
|
163
|
+
//#region src/configs/emulator/emulator-triplefold-item.ts
|
|
164
|
+
let EmulatorTripleFoldItem;
|
|
165
|
+
(function(_EmulatorTripleFoldItem) {
|
|
158
166
|
function is(value) {
|
|
159
|
-
return value instanceof
|
|
167
|
+
return value instanceof EmulatorTripleFoldItemImpl;
|
|
160
168
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
constructor(options, screen) {
|
|
165
|
-
super(options);
|
|
166
|
-
this.options = options;
|
|
167
|
-
this.screen = screen;
|
|
169
|
+
_EmulatorTripleFoldItem.is = is;
|
|
170
|
+
function isDeviceType(value) {
|
|
171
|
+
return value === "triplefold";
|
|
168
172
|
}
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
_EmulatorTripleFoldItem.isDeviceType = isDeviceType;
|
|
174
|
+
function isContent(value) {
|
|
175
|
+
return typeof value === "object" && value !== null && "name" in value && "deviceType" in value && isDeviceType(value.deviceType);
|
|
176
|
+
}
|
|
177
|
+
_EmulatorTripleFoldItem.isContent = isContent;
|
|
178
|
+
})(EmulatorTripleFoldItem || (EmulatorTripleFoldItem = {}));
|
|
179
|
+
var EmulatorTripleFoldItemImpl = class extends SerializableContentImpl {
|
|
180
|
+
constructor(emulatorFile, content) {
|
|
181
|
+
super(emulatorFile.getImageManager(), content);
|
|
182
|
+
this.emulatorFile = emulatorFile;
|
|
183
|
+
this.content = content;
|
|
184
|
+
}
|
|
185
|
+
getEmulatorFile() {
|
|
186
|
+
return this.emulatorFile;
|
|
171
187
|
}
|
|
172
188
|
};
|
|
173
|
-
function createCoverScreen(options, screen) {
|
|
174
|
-
return new CoverScreenImpl(options, screen);
|
|
175
|
-
}
|
|
176
189
|
|
|
177
190
|
//#endregion
|
|
178
|
-
//#region src/
|
|
179
|
-
let
|
|
180
|
-
(function(
|
|
191
|
+
//#region src/configs/emulator/group-item.ts
|
|
192
|
+
let EmulatorGroupItem;
|
|
193
|
+
(function(_EmulatorGroupItem) {
|
|
181
194
|
function is(value) {
|
|
182
|
-
return value instanceof
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
return value instanceof EmulatorGroupItemImpl;
|
|
196
|
+
}
|
|
197
|
+
_EmulatorGroupItem.is = is;
|
|
198
|
+
function isContent(value) {
|
|
199
|
+
return typeof value === "object" && value !== null && "name" in value && "deviceType" in value && "api" in value && "children" in value && Array.isArray(value.children) && value.children.every(EmulatorFile.isItemContent);
|
|
200
|
+
}
|
|
201
|
+
_EmulatorGroupItem.isContent = isContent;
|
|
202
|
+
})(EmulatorGroupItem || (EmulatorGroupItem = {}));
|
|
203
|
+
var EmulatorGroupItemImpl = class extends SerializableContentImpl {
|
|
204
|
+
constructor(emulatorFile, content) {
|
|
205
|
+
super(emulatorFile.getImageManager(), content);
|
|
206
|
+
this.emulatorFile = emulatorFile;
|
|
207
|
+
this.content = content;
|
|
208
|
+
}
|
|
209
|
+
getEmulatorFile() {
|
|
210
|
+
return this.emulatorFile;
|
|
211
|
+
}
|
|
212
|
+
getChildren() {
|
|
213
|
+
return this.getContent().children.map((children) => {
|
|
214
|
+
if (EmulatorBasicItem.isContent(children)) return new EmulatorBasicItemImpl(this.emulatorFile, children);
|
|
215
|
+
else if (EmulatorFoldItem.isContent(children)) return new EmulatorFoldItemImpl(this.emulatorFile, children);
|
|
216
|
+
else if (EmulatorTripleFoldItem.isContent(children)) return new EmulatorTripleFoldItemImpl(this.emulatorFile, children);
|
|
217
|
+
}).filter(Boolean);
|
|
194
218
|
}
|
|
195
219
|
};
|
|
196
|
-
function createDoubleScreen(options, screen) {
|
|
197
|
-
return new DoubleScreenImpl(options, screen);
|
|
198
|
-
}
|
|
199
220
|
|
|
200
221
|
//#endregion
|
|
201
|
-
//#region src/
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
222
|
+
//#region src/configs/emulator/emulator.ts
|
|
223
|
+
let EmulatorFile;
|
|
224
|
+
(function(_EmulatorFile) {
|
|
225
|
+
function is(value) {
|
|
226
|
+
return value instanceof EmulatorFileImpl;
|
|
227
|
+
}
|
|
228
|
+
_EmulatorFile.is = is;
|
|
229
|
+
function isItemContent(value) {
|
|
230
|
+
return typeof value === "object" && value !== null && (EmulatorBasicItem.isContent(value) || EmulatorFoldItem.isContent(value) || EmulatorTripleFoldItem.isContent(value));
|
|
231
|
+
}
|
|
232
|
+
_EmulatorFile.isItemContent = isItemContent;
|
|
233
|
+
function isContentItem(value) {
|
|
234
|
+
return typeof value === "object" && value !== null && (EmulatorGroupItem.isContent(value) || EmulatorFile.isItemContent(value));
|
|
235
|
+
}
|
|
236
|
+
_EmulatorFile.isContentItem = isContentItem;
|
|
237
|
+
})(EmulatorFile || (EmulatorFile = {}));
|
|
238
|
+
var EmulatorFileImpl = class extends SerializableFileImpl {
|
|
239
|
+
async serialize() {
|
|
240
|
+
return JSON.stringify(this.getContent(), null, 2);
|
|
241
|
+
}
|
|
242
|
+
async write() {
|
|
243
|
+
const { emulatorPath, adapter: { join } } = this.getImageManager().getOptions();
|
|
244
|
+
return this.writeToFileSystem(join(emulatorPath, "emulator.json"));
|
|
245
|
+
}
|
|
246
|
+
getItems() {
|
|
247
|
+
return this.getContent().map((item) => {
|
|
248
|
+
if (EmulatorGroupItem.isContent(item)) return new EmulatorGroupItemImpl(this, item);
|
|
249
|
+
else if (EmulatorFile.isItemContent(item)) {
|
|
250
|
+
if (EmulatorBasicItem.isContent(item)) return new EmulatorBasicItemImpl(this, item);
|
|
251
|
+
else if (EmulatorFoldItem.isContent(item)) return new EmulatorFoldItemImpl(this, item);
|
|
252
|
+
else if (EmulatorTripleFoldItem.isContent(item)) return new EmulatorTripleFoldItemImpl(this, item);
|
|
253
|
+
}
|
|
254
|
+
}).filter(Boolean);
|
|
255
|
+
}
|
|
256
|
+
findDeviceItems(options = {}) {
|
|
257
|
+
const items = [];
|
|
258
|
+
const pushDeviceItem = (item) => {
|
|
259
|
+
if (EmulatorBasicItem.is(item)) {
|
|
260
|
+
if (options.apiVersion && item.getContent().api === options.apiVersion && options.deviceType && item.getContent().deviceType === options.deviceType) items.push(item);
|
|
261
|
+
} else if (EmulatorFoldItem.is(item)) {
|
|
262
|
+
if (options.apiVersion && item.getContent().api === options.apiVersion && options.deviceType && item.getContent().deviceType === options.deviceType) items.push(item);
|
|
263
|
+
} else if (EmulatorTripleFoldItem.is(item)) {
|
|
264
|
+
if (options.apiVersion && item.getContent().api === options.apiVersion && options.deviceType && item.getContent().deviceType === options.deviceType) items.push(item);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
for (const item of this.getItems()) if (EmulatorGroupItem.is(item)) for (const child of item.getChildren()) pushDeviceItem(child);
|
|
268
|
+
else pushDeviceItem(item);
|
|
269
|
+
return items;
|
|
206
270
|
}
|
|
207
|
-
|
|
208
|
-
return this.
|
|
271
|
+
findDeviceItem(options = {}) {
|
|
272
|
+
return this.findDeviceItems(options)[0];
|
|
273
|
+
}
|
|
274
|
+
findItems(options = {}) {
|
|
275
|
+
return this.getItems().filter((item) => {
|
|
276
|
+
if (options.apiVersion && item.getContent().api === options.apiVersion && options.fullDeviceType && item.getContent().deviceType === options.fullDeviceType) return true;
|
|
277
|
+
return false;
|
|
278
|
+
});
|
|
209
279
|
}
|
|
210
|
-
|
|
211
|
-
return this.
|
|
280
|
+
findItem(options = {}) {
|
|
281
|
+
return this.findItems(options)[0];
|
|
212
282
|
}
|
|
213
283
|
toJSON() {
|
|
214
|
-
return {
|
|
284
|
+
return {
|
|
285
|
+
...super.toJSON(),
|
|
286
|
+
items: this.getItems().map((item) => item.toJSON())
|
|
287
|
+
};
|
|
215
288
|
}
|
|
216
289
|
};
|
|
217
|
-
function createEmulatorPreset(emulatorConfigItem, screenPreset) {
|
|
218
|
-
return new EmulatorPresetImpl(emulatorConfigItem, screenPreset);
|
|
219
|
-
}
|
|
220
290
|
|
|
221
291
|
//#endregion
|
|
222
|
-
//#region src/
|
|
223
|
-
let
|
|
224
|
-
(function(
|
|
292
|
+
//#region src/configs/lists/item.ts
|
|
293
|
+
let ListsFileItem;
|
|
294
|
+
(function(_ListsFileItem) {
|
|
225
295
|
function is(value) {
|
|
226
|
-
return value instanceof
|
|
227
|
-
}
|
|
228
|
-
_OuterScreen.is = is;
|
|
229
|
-
})(OuterScreen || (OuterScreen = {}));
|
|
230
|
-
var OuterScreenImpl = class extends BaseScreenImpl {
|
|
231
|
-
outerDoubleScreen;
|
|
232
|
-
constructor(options, screen) {
|
|
233
|
-
super(options);
|
|
234
|
-
this.options = options;
|
|
235
|
-
this.screen = screen;
|
|
236
|
-
if (options.double) this.outerDoubleScreen = OuterDoubleScreen.is(options.double) ? options.double : createOuterDoubleScreen(options.double, this);
|
|
296
|
+
return value instanceof ListsFileItemImpl;
|
|
237
297
|
}
|
|
238
|
-
|
|
239
|
-
|
|
298
|
+
_ListsFileItem.is = is;
|
|
299
|
+
})(ListsFileItem || (ListsFileItem = {}));
|
|
300
|
+
var ListsFileItemImpl = class extends SerializableContentImpl {
|
|
301
|
+
constructor(listsFile, content) {
|
|
302
|
+
super(listsFile.getImageManager(), content);
|
|
303
|
+
this.listsFile = listsFile;
|
|
304
|
+
this.content = content;
|
|
240
305
|
}
|
|
241
|
-
|
|
242
|
-
return this.
|
|
306
|
+
getListsFile() {
|
|
307
|
+
return this.listsFile;
|
|
243
308
|
}
|
|
244
|
-
|
|
245
|
-
this.
|
|
246
|
-
return this;
|
|
309
|
+
getContent() {
|
|
310
|
+
return this.content;
|
|
247
311
|
}
|
|
248
312
|
toJSON() {
|
|
249
313
|
return {
|
|
250
|
-
|
|
251
|
-
|
|
314
|
+
imageManager: this.getImageManager().toJSON(),
|
|
315
|
+
content: this.getContent(),
|
|
316
|
+
listsFile: this.getListsFile().toJSON()
|
|
252
317
|
};
|
|
253
318
|
}
|
|
254
319
|
};
|
|
255
|
-
function createOuterScreen(options, screen) {
|
|
256
|
-
return new OuterScreenImpl(options, screen);
|
|
257
|
-
}
|
|
258
320
|
|
|
259
321
|
//#endregion
|
|
260
|
-
//#region src/
|
|
261
|
-
let
|
|
262
|
-
(function(
|
|
322
|
+
//#region src/configs/lists/lists.ts
|
|
323
|
+
let ListsFile;
|
|
324
|
+
(function(_ListsFile) {
|
|
263
325
|
function is(value) {
|
|
264
|
-
return value instanceof
|
|
326
|
+
return value instanceof ListsFileImpl;
|
|
327
|
+
}
|
|
328
|
+
_ListsFile.is = is;
|
|
329
|
+
})(ListsFile || (ListsFile = {}));
|
|
330
|
+
var ListsFileImpl = class extends SerializableFileImpl {
|
|
331
|
+
_isChanged = false;
|
|
332
|
+
getListsFileItems() {
|
|
333
|
+
return this.getContent().map((item) => new ListsFileItemImpl(this, item));
|
|
334
|
+
}
|
|
335
|
+
removeDuplicateListFileItems(listsFileItems) {
|
|
336
|
+
this.content = listsFileItems.filter((item, index, self) => index === self.findIndex((t) => t.uuid === item.uuid)).filter((item, index, self) => index === self.findIndex((t) => t.name === item.name));
|
|
337
|
+
}
|
|
338
|
+
addListsFileItem(listsFileItem) {
|
|
339
|
+
this.content.push(listsFileItem);
|
|
340
|
+
this.removeDuplicateListFileItems(this.content);
|
|
341
|
+
this._isChanged = true;
|
|
342
|
+
return new ListsFileItemImpl(this, listsFileItem);
|
|
343
|
+
}
|
|
344
|
+
get isChanged() {
|
|
345
|
+
return this._isChanged;
|
|
346
|
+
}
|
|
347
|
+
deleteListsFileItem(listsFileItem) {
|
|
348
|
+
const index = this.content.findIndex((item) => item.uuid === listsFileItem.getContent().uuid);
|
|
349
|
+
if (index === -1) return this;
|
|
350
|
+
this.content.splice(index, 1);
|
|
351
|
+
this._isChanged = true;
|
|
352
|
+
return this;
|
|
265
353
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.
|
|
272
|
-
this.
|
|
354
|
+
async serialize() {
|
|
355
|
+
return JSON.stringify(this.getContent(), null, 2);
|
|
356
|
+
}
|
|
357
|
+
async write() {
|
|
358
|
+
if (!this.isChanged) return;
|
|
359
|
+
await this.writeToFileSystem(this.getImageManager().getListsFilePath());
|
|
360
|
+
this._isChanged = false;
|
|
273
361
|
}
|
|
274
|
-
|
|
275
|
-
return
|
|
362
|
+
toJSON() {
|
|
363
|
+
return {
|
|
364
|
+
imageManager: this.getImageManager().toJSON(),
|
|
365
|
+
content: this.getContent(),
|
|
366
|
+
listsFileItems: this.getListsFileItems().map((item) => item.toJSON())
|
|
367
|
+
};
|
|
276
368
|
}
|
|
277
369
|
};
|
|
278
|
-
function createOuterDoubleScreen(options, outerScreen) {
|
|
279
|
-
return new OuterDoubleScreenImpl(options, outerScreen);
|
|
280
|
-
}
|
|
281
370
|
|
|
282
371
|
//#endregion
|
|
283
|
-
//#region src/
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
372
|
+
//#region src/configs/product/item.ts
|
|
373
|
+
let ProductConfigItem;
|
|
374
|
+
(function(_ProductConfigItem) {
|
|
375
|
+
function is(value) {
|
|
376
|
+
return value instanceof ProductConfigItemImpl;
|
|
377
|
+
}
|
|
378
|
+
_ProductConfigItem.is = is;
|
|
379
|
+
})(ProductConfigItem || (ProductConfigItem = {}));
|
|
380
|
+
var ProductConfigItemImpl = class extends SerializableContentImpl {
|
|
381
|
+
constructor(productConfigFile, content, deviceType) {
|
|
382
|
+
super(productConfigFile.getImageManager(), content);
|
|
383
|
+
this.productConfigFile = productConfigFile;
|
|
384
|
+
this.content = content;
|
|
287
385
|
this.deviceType = deviceType;
|
|
288
|
-
this.screenPreset = screenPreset;
|
|
289
386
|
}
|
|
290
|
-
|
|
291
|
-
return this.
|
|
387
|
+
getProductConfigFile() {
|
|
388
|
+
return this.productConfigFile;
|
|
292
389
|
}
|
|
293
390
|
getDeviceType() {
|
|
294
391
|
return this.deviceType;
|
|
295
392
|
}
|
|
296
|
-
|
|
297
|
-
return this.
|
|
393
|
+
async serialize() {
|
|
394
|
+
return JSON.stringify(this.getContent(), null, 2);
|
|
395
|
+
}
|
|
396
|
+
getDevModel() {
|
|
397
|
+
switch (this.getDeviceType()) {
|
|
398
|
+
case "Phone":
|
|
399
|
+
case "2in1": return "PHEMU-FD00";
|
|
400
|
+
case "Foldable": return "PHEMU-FD01";
|
|
401
|
+
case "WideFold": return "PHEMU-FD02";
|
|
402
|
+
case "TripleFold": return "PHEMU-FD06";
|
|
403
|
+
case "2in1 Foldable": return "PCEMU-FD05";
|
|
404
|
+
case "Wearable": return "MCHEMU-AL00CN";
|
|
405
|
+
}
|
|
298
406
|
}
|
|
299
407
|
toJSON() {
|
|
300
408
|
return {
|
|
301
|
-
|
|
302
|
-
|
|
409
|
+
imageManager: this.getImageManager().toJSON(),
|
|
410
|
+
content: this.getContent(),
|
|
411
|
+
devModel: this.getDevModel(),
|
|
412
|
+
deviceType: this.getDeviceType(),
|
|
413
|
+
productConfigFile: this.getProductConfigFile().toJSON()
|
|
303
414
|
};
|
|
304
415
|
}
|
|
305
416
|
};
|
|
306
|
-
function createProductPreset(productConfig, deviceType, screenPreset) {
|
|
307
|
-
return new ProductPresetImpl(productConfig, deviceType, screenPreset);
|
|
308
|
-
}
|
|
309
417
|
|
|
310
418
|
//#endregion
|
|
311
|
-
//#region src/
|
|
312
|
-
let
|
|
313
|
-
(function(
|
|
419
|
+
//#region src/configs/product/product.ts
|
|
420
|
+
let ProductConfigFile;
|
|
421
|
+
(function(_ProductConfigFile) {
|
|
314
422
|
function is(value) {
|
|
315
|
-
return value instanceof
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
})(
|
|
319
|
-
var
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
423
|
+
return value instanceof ProductConfigFileImpl;
|
|
424
|
+
}
|
|
425
|
+
_ProductConfigFile.is = is;
|
|
426
|
+
})(ProductConfigFile || (ProductConfigFile = {}));
|
|
427
|
+
var ProductConfigFileImpl = class extends SerializableFileImpl {
|
|
428
|
+
async serialize() {
|
|
429
|
+
return JSON.stringify(this.getContent(), null, 2);
|
|
430
|
+
}
|
|
431
|
+
async write() {
|
|
432
|
+
const { imageBasePath, adapter: { join } } = this.getImageManager().getOptions();
|
|
433
|
+
return this.writeToFileSystem(join(imageBasePath, "productConfig.json"));
|
|
434
|
+
}
|
|
435
|
+
findProductConfigItems(options = {}) {
|
|
436
|
+
const content = this.getContent();
|
|
437
|
+
const items = [];
|
|
438
|
+
for (const deviceType of Object.keys(content)) {
|
|
439
|
+
if (options.deviceType && deviceType !== options.deviceType) continue;
|
|
440
|
+
for (const item of content[deviceType]) {
|
|
441
|
+
if (options.name && item.name !== options.name) continue;
|
|
442
|
+
items.push(new ProductConfigItemImpl(this, item, deviceType));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return items;
|
|
324
446
|
}
|
|
325
|
-
|
|
326
|
-
return this.
|
|
447
|
+
findProductConfigItem(options = {}) {
|
|
448
|
+
return this.findProductConfigItems(options)[0];
|
|
327
449
|
}
|
|
328
450
|
};
|
|
329
|
-
function createSingleScreen(options, screen) {
|
|
330
|
-
return new SingleScreenImpl(options, screen);
|
|
331
|
-
}
|
|
332
451
|
|
|
333
452
|
//#endregion
|
|
334
|
-
//#region src/
|
|
335
|
-
let
|
|
336
|
-
(function(
|
|
453
|
+
//#region src/devices/device.ts
|
|
454
|
+
let Device;
|
|
455
|
+
(function(_Device) {
|
|
337
456
|
function is(value) {
|
|
338
|
-
return value instanceof
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
})(
|
|
342
|
-
var
|
|
343
|
-
outerScreen;
|
|
344
|
-
coverScreen;
|
|
345
|
-
singleScreen;
|
|
346
|
-
doubleScreen;
|
|
457
|
+
return value instanceof DeviceImpl;
|
|
458
|
+
}
|
|
459
|
+
_Device.is = is;
|
|
460
|
+
})(Device || (Device = {}));
|
|
461
|
+
var DeviceImpl = class {
|
|
347
462
|
constructor(options) {
|
|
348
|
-
super(options);
|
|
349
463
|
this.options = options;
|
|
350
|
-
if (options.outer) this.outerScreen = OuterScreen.is(options.outer) ? options.outer : createOuterScreen(options.outer, this);
|
|
351
|
-
if (options.cover) this.coverScreen = CoverScreen.is(options.cover) ? options.cover : createCoverScreen(options.cover, this);
|
|
352
|
-
if (options.single) this.singleScreen = SingleScreen.is(options.single) ? options.single : createSingleScreen(options.single, this);
|
|
353
|
-
if (options.double) this.doubleScreen = DoubleScreen.is(options.double) ? options.double : createDoubleScreen(options.double, this);
|
|
354
464
|
}
|
|
355
465
|
getScreen() {
|
|
356
|
-
return this;
|
|
466
|
+
return this.options.screen;
|
|
357
467
|
}
|
|
358
|
-
|
|
359
|
-
return this.options.
|
|
468
|
+
getListsFile() {
|
|
469
|
+
return this.options.listsFile;
|
|
360
470
|
}
|
|
361
|
-
|
|
362
|
-
return this.options.
|
|
471
|
+
getListsFileItem() {
|
|
472
|
+
return this.options.listFileItem;
|
|
363
473
|
}
|
|
364
|
-
|
|
365
|
-
return this.
|
|
474
|
+
getImageManager() {
|
|
475
|
+
return this.options.imageManager;
|
|
366
476
|
}
|
|
367
|
-
|
|
368
|
-
|
|
477
|
+
_configIniFile;
|
|
478
|
+
setConfigIniFile(configIniFile) {
|
|
479
|
+
this._configIniFile = configIniFile;
|
|
369
480
|
return this;
|
|
370
481
|
}
|
|
371
|
-
|
|
372
|
-
return this.
|
|
482
|
+
getConfigIniFile() {
|
|
483
|
+
return this._configIniFile;
|
|
373
484
|
}
|
|
374
|
-
|
|
375
|
-
|
|
485
|
+
_namedIniFile;
|
|
486
|
+
getNamedIniFile() {
|
|
487
|
+
return this._namedIniFile;
|
|
488
|
+
}
|
|
489
|
+
setNamedIniFile(namedIniFile) {
|
|
490
|
+
this._namedIniFile = namedIniFile;
|
|
376
491
|
return this;
|
|
377
492
|
}
|
|
378
|
-
|
|
379
|
-
|
|
493
|
+
getExecutableUri() {
|
|
494
|
+
const { emulatorPath, adapter: { join, process } } = this.getImageManager().getOptions();
|
|
495
|
+
return join(emulatorPath, process.platform === "win32" ? "Emulator.exe" : "Emulator");
|
|
380
496
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
return this;
|
|
497
|
+
getSnapshotUri() {
|
|
498
|
+
const { deployedPath, adapter: { join } } = this.getImageManager().getOptions();
|
|
499
|
+
return join(deployedPath, this.getListsFileItem().getContent().name, "Snapshot.png");
|
|
384
500
|
}
|
|
385
|
-
|
|
386
|
-
|
|
501
|
+
async getSnapshot() {
|
|
502
|
+
const snapshotUri = this.getSnapshotUri();
|
|
503
|
+
const { adapter: { fs } } = this.getImageManager().getOptions();
|
|
504
|
+
return fromByteArray(await fs.readFile(snapshotUri));
|
|
387
505
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
return this
|
|
506
|
+
getStartCommand() {
|
|
507
|
+
const listFileItemContent = this.getListsFileItem().getContent();
|
|
508
|
+
return [this.getExecutableUri().fsPath, [
|
|
509
|
+
"-hvd",
|
|
510
|
+
listFileItemContent.name,
|
|
511
|
+
"-path",
|
|
512
|
+
this.getImageManager().getOptions().deployedPath.fsPath,
|
|
513
|
+
"-imageRoot",
|
|
514
|
+
this.getImageManager().getOptions().imageBasePath.fsPath
|
|
515
|
+
]];
|
|
516
|
+
}
|
|
517
|
+
async start() {
|
|
518
|
+
const { emulatorPath, adapter: { child_process } } = this.getImageManager().getOptions();
|
|
519
|
+
const [executableUri, args] = this.getStartCommand();
|
|
520
|
+
return child_process.spawn(executableUri, args, {
|
|
521
|
+
cwd: emulatorPath.fsPath,
|
|
522
|
+
stdio: [
|
|
523
|
+
"ignore",
|
|
524
|
+
"pipe",
|
|
525
|
+
"pipe"
|
|
526
|
+
]
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
getStopCommand() {
|
|
530
|
+
const listFileItemContent = this.getListsFileItem().getContent();
|
|
531
|
+
return [this.getExecutableUri().fsPath, ["-stop", listFileItemContent.name]];
|
|
532
|
+
}
|
|
533
|
+
async stop() {
|
|
534
|
+
const { emulatorPath, adapter: { child_process } } = this.getImageManager().getOptions();
|
|
535
|
+
const [executableUri, args] = this.getStopCommand();
|
|
536
|
+
return child_process.spawn(executableUri, args, {
|
|
537
|
+
cwd: emulatorPath.fsPath,
|
|
538
|
+
stdio: [
|
|
539
|
+
"ignore",
|
|
540
|
+
"pipe",
|
|
541
|
+
"pipe"
|
|
542
|
+
]
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
async delete() {
|
|
546
|
+
const { deployedPath, adapter: { join, fs } } = this.getImageManager().getOptions();
|
|
547
|
+
await Promise.allSettled([
|
|
548
|
+
fs.delete(join(deployedPath, this.getListsFileItem().getContent().name), { recursive: true }),
|
|
549
|
+
fs.delete(join(deployedPath, `${this.getListsFileItem().getContent().name}.ini`), { recursive: false }),
|
|
550
|
+
this.getImageManager().readListsFile().then(async (listsFile) => {
|
|
551
|
+
const listsFileItem = listsFile.getListsFileItems().find((item) => {
|
|
552
|
+
return item.getContent().name === this.getListsFileItem().getContent().name;
|
|
553
|
+
});
|
|
554
|
+
if (!listsFileItem) return;
|
|
555
|
+
await listsFile.deleteListsFileItem(listsFileItem).write();
|
|
556
|
+
})
|
|
557
|
+
]);
|
|
558
|
+
}
|
|
559
|
+
async getStorageSize() {
|
|
560
|
+
const { deployedPath, adapter: { join, fs } } = this.getImageManager().getOptions();
|
|
561
|
+
return (await fs.stat(join(deployedPath, this.getListsFileItem().getContent().name))).size;
|
|
562
|
+
}
|
|
563
|
+
_watcher;
|
|
564
|
+
async getWatcher() {
|
|
565
|
+
if (this._watcher && !this._watcher.isDisposed) return this._watcher;
|
|
566
|
+
const { deployedPath, adapter: { fs, join } } = this.getImageManager().getOptions();
|
|
567
|
+
this._watcher = await fs.createWatcher(new RelativePattern(join(deployedPath, this.getListsFileItem().getContent().name), "**"));
|
|
568
|
+
return this._watcher;
|
|
569
|
+
}
|
|
570
|
+
toJSON() {
|
|
571
|
+
return {
|
|
572
|
+
screen: this.getScreen(),
|
|
573
|
+
listsFile: this.getListsFile().toJSON(),
|
|
574
|
+
listsFileItem: this.getListsFileItem().toJSON(),
|
|
575
|
+
configIniFile: this.getConfigIniFile().toJSON(),
|
|
576
|
+
namedIniFile: this.getNamedIniFile().toJSON(),
|
|
577
|
+
executableUri: this.getExecutableUri().toJSON(),
|
|
578
|
+
snapshotUri: this.getSnapshotUri().toJSON(),
|
|
579
|
+
startCommand: this.getStartCommand(),
|
|
580
|
+
stopCommand: this.getStopCommand()
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/configs/named-ini/named-ini.ts
|
|
587
|
+
let NamedIniFile;
|
|
588
|
+
(function(_NamedIniFile) {
|
|
589
|
+
function is(value) {
|
|
590
|
+
return value instanceof NamedIniFileImpl;
|
|
591
|
+
}
|
|
592
|
+
_NamedIniFile.is = is;
|
|
593
|
+
})(NamedIniFile || (NamedIniFile = {}));
|
|
594
|
+
var NamedIniFileImpl = class extends SerializableFileImpl {
|
|
595
|
+
constructor(device, namedIniFilePath, content) {
|
|
596
|
+
super(device.getImageManager(), content);
|
|
597
|
+
this.device = device;
|
|
598
|
+
this.namedIniFilePath = namedIniFilePath;
|
|
599
|
+
this.content = content;
|
|
600
|
+
}
|
|
601
|
+
getDevice() {
|
|
602
|
+
return this.device;
|
|
603
|
+
}
|
|
604
|
+
static getFileUri(device) {
|
|
605
|
+
const { deployedPath, adapter: { join } } = device.getImageManager().getOptions();
|
|
606
|
+
return join(deployedPath, `${device.getListsFileItem().getContent().name}.ini`);
|
|
607
|
+
}
|
|
608
|
+
getFileUri() {
|
|
609
|
+
return this.namedIniFilePath;
|
|
610
|
+
}
|
|
611
|
+
static async safeReadAndParse(device) {
|
|
612
|
+
try {
|
|
613
|
+
const { adapter: { fs } } = device.getImageManager().getOptions();
|
|
614
|
+
const namedIniFileUri = this.getFileUri(device);
|
|
615
|
+
const namedIniFileContent = await fs.readFile(namedIniFileUri).then((buffer) => buffer.toString(), () => void 0);
|
|
616
|
+
if (!namedIniFileContent?.length) return;
|
|
617
|
+
return INI.parse(namedIniFileContent);
|
|
618
|
+
} catch {}
|
|
619
|
+
}
|
|
620
|
+
async serialize() {
|
|
621
|
+
return INI.stringify(this.getContent());
|
|
622
|
+
}
|
|
623
|
+
async write() {
|
|
624
|
+
const { deployedPath, adapter: { join } } = this.getImageManager().getOptions();
|
|
625
|
+
return this.writeToFileSystem(join(deployedPath, `${this.getDevice().getListsFileItem().getContent().name}.ini`));
|
|
626
|
+
}
|
|
627
|
+
toJSON() {
|
|
628
|
+
return {
|
|
629
|
+
imageManager: this.getImageManager().toJSON(),
|
|
630
|
+
content: this.getContent(),
|
|
631
|
+
fileUri: this.getFileUri().toJSON()
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/screens/customize-screen.ts
|
|
638
|
+
let CustomizeScreen;
|
|
639
|
+
(function(_CustomizeScreen) {
|
|
640
|
+
function is(value) {
|
|
641
|
+
return value instanceof CustomizeScreenImpl;
|
|
642
|
+
}
|
|
643
|
+
_CustomizeScreen.is = is;
|
|
644
|
+
})(CustomizeScreen || (CustomizeScreen = {}));
|
|
645
|
+
var CustomizeScreenImpl = class {
|
|
646
|
+
constructor(screenPreset, options) {
|
|
647
|
+
this.screenPreset = screenPreset;
|
|
648
|
+
this.options = options;
|
|
649
|
+
}
|
|
650
|
+
getConfigName() {
|
|
651
|
+
return this.options?.configName ?? "Customize_01";
|
|
652
|
+
}
|
|
653
|
+
getDiagonalSize() {
|
|
654
|
+
return this.options?.diagonalSize ?? 0;
|
|
655
|
+
}
|
|
656
|
+
getResolutionWidth() {
|
|
657
|
+
return this.options?.resolutionWidth ?? 0;
|
|
658
|
+
}
|
|
659
|
+
getResolutionHeight() {
|
|
660
|
+
return this.options?.resolutionHeight ?? 0;
|
|
391
661
|
}
|
|
392
662
|
getDensity() {
|
|
393
|
-
return this.options
|
|
663
|
+
return this.options?.density ?? 0;
|
|
394
664
|
}
|
|
395
|
-
|
|
396
|
-
this.
|
|
397
|
-
|
|
665
|
+
getScreenPreset() {
|
|
666
|
+
return this.screenPreset;
|
|
667
|
+
}
|
|
668
|
+
toJSON() {
|
|
669
|
+
return {
|
|
670
|
+
configName: this.getConfigName(),
|
|
671
|
+
diagonalSize: this.getDiagonalSize(),
|
|
672
|
+
resolutionWidth: this.getResolutionWidth(),
|
|
673
|
+
resolutionHeight: this.getResolutionHeight(),
|
|
674
|
+
density: this.getDensity()
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
//#endregion
|
|
680
|
+
//#region src/screens/customize-foldable-screen.ts
|
|
681
|
+
let CustomizeFoldableScreen;
|
|
682
|
+
(function(_CustomizeFoldableScreen) {
|
|
683
|
+
function is(value) {
|
|
684
|
+
return value instanceof CustomizeFoldableScreenImpl;
|
|
685
|
+
}
|
|
686
|
+
_CustomizeFoldableScreen.is = is;
|
|
687
|
+
})(CustomizeFoldableScreen || (CustomizeFoldableScreen = {}));
|
|
688
|
+
var CustomizeFoldableScreenImpl = class extends CustomizeScreenImpl {
|
|
689
|
+
constructor(screenPreset, options, foldableOptions) {
|
|
690
|
+
super(screenPreset, options);
|
|
691
|
+
this.screenPreset = screenPreset;
|
|
692
|
+
this.options = options;
|
|
693
|
+
this.foldableOptions = foldableOptions;
|
|
694
|
+
}
|
|
695
|
+
getCoverResolutionWidth() {
|
|
696
|
+
return this.foldableOptions?.coverResolutionWidth ?? 0;
|
|
697
|
+
}
|
|
698
|
+
getCoverResolutionHeight() {
|
|
699
|
+
return this.foldableOptions?.coverResolutionHeight ?? 0;
|
|
700
|
+
}
|
|
701
|
+
getCoverDiagonalSize() {
|
|
702
|
+
return this.foldableOptions?.coverDiagonalSize ?? 0;
|
|
398
703
|
}
|
|
399
704
|
toJSON() {
|
|
400
705
|
return {
|
|
401
706
|
...super.toJSON(),
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
outer: this.outerScreen?.toJSON(),
|
|
406
|
-
cover: this.coverScreen?.toJSON(),
|
|
407
|
-
single: this.singleScreen?.toJSON()
|
|
707
|
+
coverResolutionWidth: this.getCoverResolutionWidth(),
|
|
708
|
+
coverResolutionHeight: this.getCoverResolutionHeight(),
|
|
709
|
+
coverDiagonalSize: this.getCoverDiagonalSize()
|
|
408
710
|
};
|
|
409
711
|
}
|
|
410
712
|
};
|
|
411
|
-
function createScreen(options) {
|
|
412
|
-
return new ScreenImpl(options);
|
|
413
|
-
}
|
|
414
713
|
|
|
415
714
|
//#endregion
|
|
416
715
|
//#region src/screens/screen-preset.ts
|
|
417
716
|
let ScreenPreset;
|
|
418
717
|
(function(_ScreenPreset) {
|
|
419
|
-
let ScreenOptions;
|
|
420
|
-
(function(_ScreenOptions) {
|
|
421
|
-
function is(value) {
|
|
422
|
-
return typeof value === "object" && value !== null && "screen" in value && Screen.is(value.screen);
|
|
423
|
-
}
|
|
424
|
-
_ScreenOptions.is = is;
|
|
425
|
-
})(ScreenOptions || (ScreenOptions = _ScreenPreset.ScreenOptions || (_ScreenPreset.ScreenOptions = {})));
|
|
426
|
-
let ProductOptions;
|
|
427
|
-
(function(_ProductOptions) {
|
|
428
|
-
function is(value) {
|
|
429
|
-
return typeof value === "object" && value !== null && "image" in value && "productConfig" in value && ProductConfigItem.is(value.productConfig);
|
|
430
|
-
}
|
|
431
|
-
_ProductOptions.is = is;
|
|
432
|
-
})(ProductOptions || (ProductOptions = _ScreenPreset.ProductOptions || (_ScreenPreset.ProductOptions = {})));
|
|
433
|
-
let EmulatorOptions;
|
|
434
|
-
(function(_EmulatorOptions) {
|
|
435
|
-
function is(value) {
|
|
436
|
-
return typeof value === "object" && value !== null && "image" in value && "emulatorConfig" in value;
|
|
437
|
-
}
|
|
438
|
-
_EmulatorOptions.is = is;
|
|
439
|
-
})(EmulatorOptions || (EmulatorOptions = _ScreenPreset.EmulatorOptions || (_ScreenPreset.EmulatorOptions = {})));
|
|
440
718
|
function is(value) {
|
|
441
719
|
return value instanceof ScreenPresetImpl;
|
|
442
720
|
}
|
|
443
721
|
_ScreenPreset.is = is;
|
|
444
722
|
})(ScreenPreset || (ScreenPreset = {}));
|
|
445
723
|
var ScreenPresetImpl = class {
|
|
446
|
-
emulatorPreset;
|
|
447
|
-
productPreset;
|
|
448
724
|
constructor(options) {
|
|
449
725
|
this.options = options;
|
|
450
|
-
this._screen = this.getScreen();
|
|
451
|
-
this.setEmulatorPreset();
|
|
452
|
-
this.setProductPreset();
|
|
453
726
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
if (ScreenPreset.ScreenOptions.is(this.options)) return this.options.screen;
|
|
457
|
-
if (this._screen) return this._screen;
|
|
458
|
-
if (ScreenPreset.ProductOptions.is(this.options)) {
|
|
459
|
-
this._screen = createScreen({
|
|
460
|
-
width: Number(this.options.productConfig.screenWidth),
|
|
461
|
-
height: Number(this.options.productConfig.screenHeight),
|
|
462
|
-
diagonal: Number(this.options.productConfig.screenDiagonal),
|
|
463
|
-
density: Number(this.options.productConfig.screenDensity),
|
|
464
|
-
apiVersion: Number.parseInt(this.options.image.getApiVersion()),
|
|
465
|
-
deviceType: this.options.image.getSnakecaseDeviceType()
|
|
466
|
-
});
|
|
467
|
-
if (this.options.productConfig.outerScreenWidth && this.options.productConfig.outerScreenHeight && this.options.productConfig.outerScreenDiagonal) this._screen.setOuterScreen(createOuterScreen({
|
|
468
|
-
width: Number(this.options.productConfig.outerScreenWidth),
|
|
469
|
-
height: Number(this.options.productConfig.outerScreenHeight),
|
|
470
|
-
diagonal: Number(this.options.productConfig.outerScreenDiagonal)
|
|
471
|
-
}, this._screen));
|
|
472
|
-
if (this.options.productConfig.outerDoubleScreenWidth && this.options.productConfig.outerDoubleScreenHeight && this.options.productConfig.outerDoubleScreenDiagonal) this._screen.getOuterScreen()?.setOuterDoubleScreen(createOuterDoubleScreen({
|
|
473
|
-
width: Number(this.options.productConfig.outerDoubleScreenWidth),
|
|
474
|
-
height: Number(this.options.productConfig.outerDoubleScreenHeight),
|
|
475
|
-
diagonal: Number(this.options.productConfig.outerDoubleScreenDiagonal)
|
|
476
|
-
}, this._screen.getOuterScreen()));
|
|
477
|
-
return this._screen;
|
|
478
|
-
}
|
|
479
|
-
if (ScreenPreset.EmulatorOptions.is(this.options)) {
|
|
480
|
-
this._screen = createScreen({
|
|
481
|
-
width: this.options.emulatorConfig.resolutionWidth,
|
|
482
|
-
height: this.options.emulatorConfig.resolutionHeight,
|
|
483
|
-
diagonal: this.options.emulatorConfig.diagonalSize,
|
|
484
|
-
density: this.options.emulatorConfig.density,
|
|
485
|
-
apiVersion: Number.parseInt(this.options.image.getApiVersion()),
|
|
486
|
-
deviceType: this.options.image.getSnakecaseDeviceType()
|
|
487
|
-
});
|
|
488
|
-
if (this.options.emulatorConfig.coverResolutionWidth && this.options.emulatorConfig.coverResolutionHeight && this.options.emulatorConfig.coverDiagonalSize) this._screen.setCoverScreen(createCoverScreen({
|
|
489
|
-
width: this.options.emulatorConfig.coverResolutionWidth,
|
|
490
|
-
height: this.options.emulatorConfig.coverResolutionHeight,
|
|
491
|
-
diagonal: this.options.emulatorConfig.coverDiagonalSize
|
|
492
|
-
}, this._screen));
|
|
493
|
-
if (PhoneAllEmulatorConfigItem.is(this.options.emulatorConfig)) {
|
|
494
|
-
if (this.options.emulatorConfig.singleResolutionWidth && this.options.emulatorConfig.singleResolutionHeight && this.options.emulatorConfig.singleDiagonalSize) this._screen.setSingleScreen(createSingleScreen({
|
|
495
|
-
width: this.options.emulatorConfig.singleResolutionWidth,
|
|
496
|
-
height: this.options.emulatorConfig.singleResolutionHeight,
|
|
497
|
-
diagonal: this.options.emulatorConfig.singleDiagonalSize
|
|
498
|
-
}, this._screen));
|
|
499
|
-
if (this.options.emulatorConfig.doubleResolutionWidth && this.options.emulatorConfig.doubleResolutionHeight && this.options.emulatorConfig.doubleDiagonalSize) this._screen.setDoubleScreen(createDoubleScreen({
|
|
500
|
-
width: this.options.emulatorConfig.doubleResolutionWidth,
|
|
501
|
-
height: this.options.emulatorConfig.doubleResolutionHeight,
|
|
502
|
-
diagonal: this.options.emulatorConfig.doubleDiagonalSize
|
|
503
|
-
}, this._screen));
|
|
504
|
-
}
|
|
505
|
-
return this._screen;
|
|
506
|
-
}
|
|
507
|
-
throw new Error("Invalid createScreenPreset options.");
|
|
508
|
-
}
|
|
509
|
-
getProductConfigItemsByScreenOptions() {
|
|
510
|
-
if (!ScreenPreset.ScreenOptions.is(this.options)) return;
|
|
511
|
-
for (const [pascalCaseDeviceType, productConfigItem] of Object.entries(this.options.productConfig ?? {})) if (pascalCaseDeviceType === "2in1" && this.getScreen().getSnakecaseDeviceType() === "2in1") return [productConfigItem, pascalCaseDeviceType];
|
|
512
|
-
else if (pascalCaseDeviceType === "2in1 Foldable" && this.getScreen().getSnakecaseDeviceType() === "2in1_foldable") return [productConfigItem, pascalCaseDeviceType];
|
|
513
|
-
else if (pascalCaseDeviceType === "Foldable" && this.getScreen().getSnakecaseDeviceType() === "foldable") return [productConfigItem, pascalCaseDeviceType];
|
|
514
|
-
else if (pascalCaseDeviceType === "Phone" && this.getScreen().getSnakecaseDeviceType() === "phone") return [productConfigItem, pascalCaseDeviceType];
|
|
515
|
-
else if (pascalCaseDeviceType === "TV" && this.getScreen().getSnakecaseDeviceType() === "tv") return [productConfigItem, pascalCaseDeviceType];
|
|
516
|
-
else if (pascalCaseDeviceType === "Tablet" && this.getScreen().getSnakecaseDeviceType() === "tablet") return [productConfigItem, pascalCaseDeviceType];
|
|
517
|
-
else if (pascalCaseDeviceType === "TripleFold" && this.getScreen().getSnakecaseDeviceType() === "triplefold") return [productConfigItem, pascalCaseDeviceType];
|
|
518
|
-
else if (pascalCaseDeviceType === "Wearable" && this.getScreen().getSnakecaseDeviceType() === "wearable") return [productConfigItem, pascalCaseDeviceType];
|
|
519
|
-
else if (pascalCaseDeviceType === "WideFold" && this.getScreen().getSnakecaseDeviceType() === "widefold") return [productConfigItem, pascalCaseDeviceType];
|
|
520
|
-
else if (pascalCaseDeviceType.toLowerCase() === this.getScreen().getSnakecaseDeviceType().toLowerCase()) return [productConfigItem, pascalCaseDeviceType];
|
|
521
|
-
}
|
|
522
|
-
setProductPreset() {
|
|
523
|
-
if (ScreenPreset.ScreenOptions.is(this.options)) {
|
|
524
|
-
const [productConfigItems = [], pascalCaseDeviceType] = this.getProductConfigItemsByScreenOptions() ?? [];
|
|
525
|
-
if (!pascalCaseDeviceType || !productConfigItems.length) return;
|
|
526
|
-
for (const productConfigItem of productConfigItems) {
|
|
527
|
-
if (this.getScreen().getWidth() !== Number(productConfigItem.screenWidth) || this.getScreen().getHeight() !== Number(productConfigItem.screenHeight) || this.getScreen().getDiagonal() !== Number(productConfigItem.screenDiagonal) || this.getScreen().getDensity() !== Number(productConfigItem.screenDensity)) continue;
|
|
528
|
-
if (productConfigItem.outerScreenWidth && productConfigItem.outerScreenHeight && productConfigItem.outerScreenDiagonal) {
|
|
529
|
-
const outerScreen = this.getScreen().getOuterScreen();
|
|
530
|
-
if (!outerScreen) continue;
|
|
531
|
-
if (outerScreen.getWidth() !== Number(productConfigItem.outerScreenWidth) || outerScreen.getHeight() !== Number(productConfigItem.outerScreenHeight) || outerScreen.getDiagonal() !== Number(productConfigItem.outerScreenDiagonal)) continue;
|
|
532
|
-
}
|
|
533
|
-
if (productConfigItem.outerDoubleScreenWidth && productConfigItem.outerDoubleScreenHeight && productConfigItem.outerDoubleScreenDiagonal) {
|
|
534
|
-
const outerDoubleScreen = this.getScreen().getOuterScreen()?.getOuterDoubleScreen();
|
|
535
|
-
if (!outerDoubleScreen) continue;
|
|
536
|
-
if (outerDoubleScreen.getWidth() !== Number(productConfigItem.outerDoubleScreenWidth) || outerDoubleScreen.getHeight() !== Number(productConfigItem.outerDoubleScreenHeight) || outerDoubleScreen.getDiagonal() !== Number(productConfigItem.outerDoubleScreenDiagonal)) continue;
|
|
537
|
-
}
|
|
538
|
-
this.productPreset = createProductPreset(productConfigItem, pascalCaseDeviceType, this);
|
|
539
|
-
return;
|
|
540
|
-
}
|
|
541
|
-
} else if (ScreenPreset.ProductOptions.is(this.options)) this.productPreset = createProductPreset(this.options.productConfig, this.options.pascalCaseDeviceType, this);
|
|
542
|
-
else if (ScreenPreset.EmulatorOptions.is(this.options)) this.emulatorPreset = createEmulatorPreset(this.options.emulatorConfig, this);
|
|
543
|
-
}
|
|
544
|
-
setEmulatorPreset() {
|
|
545
|
-
if (ScreenPreset.ScreenOptions.is(this.options)) {
|
|
546
|
-
if (!this.options.emulatorConfig) return;
|
|
547
|
-
for (const parentConfigItem of this.options.emulatorConfig) {
|
|
548
|
-
if (parentConfigItem.api !== this.options.screen.getApiVersion()) continue;
|
|
549
|
-
if (ParentEmulatorConfigItem.is(parentConfigItem) && parentConfigItem.deviceType === this.options.screen.getSnakecaseDeviceType()) {
|
|
550
|
-
this.emulatorPreset = createEmulatorPreset(parentConfigItem, this);
|
|
551
|
-
return;
|
|
552
|
-
}
|
|
553
|
-
if (GroupPhoneAllEmulatorConfigItem.is(parentConfigItem) && isPhoneAllSnakecaseDeviceType(this.options.screen.getSnakecaseDeviceType())) {
|
|
554
|
-
for (const childrenConfigItem of parentConfigItem.children) if (PhoneAllEmulatorConfigItem.is(childrenConfigItem) && childrenConfigItem.deviceType === this.options.screen.getSnakecaseDeviceType()) {
|
|
555
|
-
this.emulatorPreset = createEmulatorPreset(childrenConfigItem, this);
|
|
556
|
-
return;
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
if (GroupPCAllEmulatorConfigItem.is(parentConfigItem) && isPCAllSnakecaseDeviceType(this.options.screen.getSnakecaseDeviceType())) {
|
|
560
|
-
for (const childrenConfigItem of parentConfigItem.children) if (PCAllEmulatorConfigItem.is(childrenConfigItem) && childrenConfigItem.deviceType === this.options.screen.getSnakecaseDeviceType()) {
|
|
561
|
-
this.emulatorPreset = createEmulatorPreset(childrenConfigItem, this);
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
} else if (ScreenPreset.EmulatorOptions.is(this.options)) this.emulatorPreset = createEmulatorPreset(this.options.emulatorConfig, this);
|
|
727
|
+
getEmulatorDeviceItem() {
|
|
728
|
+
return this.options.emulatorDeviceItem;
|
|
567
729
|
}
|
|
568
|
-
|
|
569
|
-
return this.
|
|
730
|
+
getProductConfigItem() {
|
|
731
|
+
return this.options.productConfigItem;
|
|
570
732
|
}
|
|
571
|
-
|
|
572
|
-
|
|
733
|
+
_customizeScreen;
|
|
734
|
+
getCustomizeScreenConfig() {
|
|
735
|
+
if (this._customizeScreen) return this._customizeScreen;
|
|
736
|
+
if (this.getEmulatorDeviceItem().getContent().deviceType === "foldable" && this.options.productConfigItem.getContent().name === "Customize" && "customizeScreen" in this.options && "customizeFoldableScreen" in this.options) this._customizeScreen = new CustomizeFoldableScreenImpl(this, this.options.customizeScreen, this.options.customizeFoldableScreen);
|
|
737
|
+
else if (this.options.productConfigItem.getContent().name === "Customize" && "customizeScreen" in this.options) this._customizeScreen = new CustomizeScreenImpl(this, this.options.customizeScreen);
|
|
738
|
+
return this._customizeScreen;
|
|
573
739
|
}
|
|
574
740
|
toJSON() {
|
|
575
741
|
return {
|
|
576
|
-
|
|
577
|
-
|
|
742
|
+
customizeScreenConfig: this.getCustomizeScreenConfig()?.toJSON(),
|
|
743
|
+
emulatorDeviceItem: this.getEmulatorDeviceItem().toJSON(),
|
|
744
|
+
productConfigItem: this.getProductConfigItem().toJSON()
|
|
578
745
|
};
|
|
579
746
|
}
|
|
580
747
|
};
|
|
581
|
-
function createScreenPreset(options) {
|
|
582
|
-
return new ScreenPresetImpl(options);
|
|
583
|
-
}
|
|
584
748
|
|
|
585
749
|
//#endregion
|
|
586
|
-
//#region src/
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
this.options = options;
|
|
592
|
-
this.uuid = image.getImageManager().getOptions().crypto.randomUUID();
|
|
593
|
-
}
|
|
594
|
-
getOptions() {
|
|
595
|
-
return this.options;
|
|
596
|
-
}
|
|
597
|
-
getImage() {
|
|
598
|
-
return this.image;
|
|
599
|
-
}
|
|
600
|
-
getScreen() {
|
|
601
|
-
if (this.options.screen instanceof ScreenPresetImpl) return this.options.screen.getScreen();
|
|
602
|
-
return this.options.screen;
|
|
750
|
+
//#region src/images/base-image.ts
|
|
751
|
+
let BaseImage;
|
|
752
|
+
(function(_BaseImage) {
|
|
753
|
+
function is(value) {
|
|
754
|
+
return value instanceof BaseImageImpl;
|
|
603
755
|
}
|
|
604
|
-
|
|
605
|
-
|
|
756
|
+
_BaseImage.is = is;
|
|
757
|
+
})(BaseImage || (BaseImage = {}));
|
|
758
|
+
var BaseImageImpl = class {
|
|
759
|
+
constructor(options) {
|
|
760
|
+
this.options = options;
|
|
606
761
|
}
|
|
607
|
-
|
|
608
|
-
this.
|
|
609
|
-
return this;
|
|
762
|
+
getImageManager() {
|
|
763
|
+
return this.options.imageManager;
|
|
610
764
|
}
|
|
611
|
-
|
|
612
|
-
return this.
|
|
765
|
+
getRelativePath() {
|
|
766
|
+
return this.options.relativePath;
|
|
613
767
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
this.
|
|
617
|
-
return this;
|
|
768
|
+
getFullPath() {
|
|
769
|
+
const { imageBasePath, adapter: { join } } = this.getImageManager().getOptions();
|
|
770
|
+
return join(imageBasePath, this.getRelativePath());
|
|
618
771
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
this.cachedIni = ini;
|
|
622
|
-
return this;
|
|
772
|
+
getApiVersion() {
|
|
773
|
+
return this.options.apiVersion;
|
|
623
774
|
}
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
"name": this.options.name,
|
|
630
|
-
"apiVersion": this.image.getApiVersion(),
|
|
631
|
-
"cpuNumber": this.options.cpuNumber.toFixed(),
|
|
632
|
-
"diagonalSize": screen.getDiagonal().toFixed(2),
|
|
633
|
-
"resolutionHeight": screen.getHeight().toFixed(),
|
|
634
|
-
"resolutionWidth": screen.getWidth().toFixed(),
|
|
635
|
-
"density": screen.getDensity().toFixed(),
|
|
636
|
-
"memoryRamSize": this.options.memorySize.toFixed(),
|
|
637
|
-
"dataDiskSize": this.options.diskSize.toFixed(),
|
|
638
|
-
"path": path.resolve(deployedPath, this.options.name),
|
|
639
|
-
"type": this.image.getSnakecaseDeviceType(),
|
|
640
|
-
"uuid": this.uuid,
|
|
641
|
-
"version": this.image.getVersion(),
|
|
642
|
-
"imageDir": this.image.getPath().split(",").join(path.sep) + path.sep,
|
|
643
|
-
"showVersion": `${this.image.getTargetOS()} ${this.image.getTargetVersion()}(${this.image.getApiVersion()})`,
|
|
644
|
-
"harmonyos.sdk.path": imageBasePath,
|
|
645
|
-
"harmonyos.config.path": configPath,
|
|
646
|
-
"harmonyos.log.path": logPath,
|
|
647
|
-
"hw.apiName": this.image.getTargetVersion(),
|
|
648
|
-
"abi": this.image.getArch(),
|
|
649
|
-
"harmonyOSVersion": `${this.image.getTargetOS()}-${this.image.getTargetVersion()}`,
|
|
650
|
-
"guestVersion": `${this.image.getTargetOS()} ${this.image.getVersion()}(${this.image.getReleaseType()})`
|
|
651
|
-
};
|
|
652
|
-
if (this.options.screen instanceof ScreenPresetImpl) {
|
|
653
|
-
const productConfig = this.options.screen.getProductPreset()?.getProductConfig();
|
|
654
|
-
if (productConfig?.devModel) list.devModel = productConfig.devModel;
|
|
655
|
-
if (productConfig?.name) list.model = productConfig.name;
|
|
656
|
-
}
|
|
657
|
-
return list;
|
|
658
|
-
}
|
|
659
|
-
buildIni(options = {}) {
|
|
660
|
-
if (this.cachedIni) return this.cachedIni;
|
|
661
|
-
const listConfig = this.buildList();
|
|
662
|
-
const screen = this.getScreen();
|
|
663
|
-
const is2in1Foldable = listConfig.type === "2in1_foldable";
|
|
664
|
-
const screenPreset = this.options.screen instanceof ScreenPresetImpl ? this.options.screen.getProductPreset() : null;
|
|
665
|
-
const productConfig = screenPreset?.getProductConfig();
|
|
666
|
-
const useDualScreen = is2in1Foldable && productConfig?.outerScreenWidth != null && productConfig?.outerScreenHeight != null && productConfig?.outerScreenDiagonal != null;
|
|
667
|
-
const singleDiagonal = useDualScreen ? productConfig.outerScreenDiagonal : screen.getDiagonal().toString();
|
|
668
|
-
const singleHeight = useDualScreen ? productConfig.outerScreenHeight : screen.getHeight().toString();
|
|
669
|
-
const singleWidth = useDualScreen ? productConfig.outerScreenWidth : screen.getWidth().toString();
|
|
670
|
-
const doubleDiagonal = useDualScreen ? productConfig.screenDiagonal : void 0;
|
|
671
|
-
const doubleHeight = useDualScreen ? productConfig.screenHeight : void 0;
|
|
672
|
-
const doubleWidth = useDualScreen ? productConfig.screenWidth : void 0;
|
|
673
|
-
const ini = {
|
|
674
|
-
"name": listConfig.name,
|
|
675
|
-
"deviceType": listConfig.type,
|
|
676
|
-
"deviceModel": listConfig.devModel,
|
|
677
|
-
"productModel": listConfig.model,
|
|
678
|
-
"vendorCountry": options.vendorCountry ?? "CN",
|
|
679
|
-
"uuid": this.uuid,
|
|
680
|
-
"configPath": listConfig["harmonyos.config.path"],
|
|
681
|
-
"logPath": listConfig["harmonyos.log.path"],
|
|
682
|
-
"sdkPath": listConfig["harmonyos.sdk.path"],
|
|
683
|
-
"imageSubPath": listConfig.imageDir,
|
|
684
|
-
"instancePath": listConfig.path,
|
|
685
|
-
"os.osVersion": `${this.image.getTargetOS()} ${this.image.getTargetVersion()}(${this.image.getApiVersion()})`,
|
|
686
|
-
"os.apiVersion": this.image.getApiVersion(),
|
|
687
|
-
"os.softwareVersion": this.image.getVersion(),
|
|
688
|
-
"os.isPublic": options.isPublic ?? true ? "true" : "false",
|
|
689
|
-
"hw.cpu.arch": listConfig.abi,
|
|
690
|
-
"hw.cpu.ncore": listConfig.cpuNumber,
|
|
691
|
-
"hw.lcd.density": screen.getDensity().toFixed(),
|
|
692
|
-
"hw.lcd.single.diagonalSize": singleDiagonal,
|
|
693
|
-
"hw.lcd.single.height": singleHeight,
|
|
694
|
-
"hw.lcd.single.width": singleWidth,
|
|
695
|
-
"hw.lcd.number": useDualScreen ? "2" : "1",
|
|
696
|
-
"hw.ramSize": listConfig.memoryRamSize,
|
|
697
|
-
"hw.dataPartitionSize": listConfig.dataDiskSize,
|
|
698
|
-
"isCustomize": screenPreset ? "false" : "true",
|
|
699
|
-
"hw.hdc.port": "notset",
|
|
700
|
-
...options.overrides
|
|
701
|
-
};
|
|
702
|
-
if (useDualScreen && doubleDiagonal != null && doubleHeight != null && doubleWidth != null) {
|
|
703
|
-
ini["hw.lcd.double.diagonalSize"] = doubleDiagonal;
|
|
704
|
-
ini["hw.lcd.double.height"] = doubleHeight;
|
|
705
|
-
ini["hw.lcd.double.width"] = doubleWidth;
|
|
706
|
-
}
|
|
707
|
-
if (screenPreset && productConfig && !useDualScreen) {
|
|
708
|
-
if (productConfig.outerScreenHeight) ini["hw.phy.height"] = productConfig.outerScreenHeight;
|
|
709
|
-
if (productConfig.outerScreenWidth) ini["hw.phy.width"] = productConfig.outerScreenWidth;
|
|
775
|
+
async isDownloaded() {
|
|
776
|
+
try {
|
|
777
|
+
return (await this.getImageManager().getLocalImages()).some((localImage) => localImage.getFullPath().toString() === this.getFullPath().toString());
|
|
778
|
+
} catch {
|
|
779
|
+
return false;
|
|
710
780
|
}
|
|
711
|
-
return ini;
|
|
712
781
|
}
|
|
713
|
-
|
|
714
|
-
return `${Object.entries(this.buildIni()).filter(([, value]) => value !== void 0 && value !== null).map(([key, value]) => `${key}=${value}`).join("\n")}\n`;
|
|
715
|
-
}
|
|
716
|
-
buildDeviceIni() {
|
|
782
|
+
toJSON() {
|
|
717
783
|
return {
|
|
718
|
-
|
|
719
|
-
|
|
784
|
+
imageType: this.imageType,
|
|
785
|
+
imageManager: this.getImageManager().toJSON(),
|
|
786
|
+
relativePath: this.getRelativePath(),
|
|
787
|
+
fullPath: this.getFullPath().toJSON(),
|
|
788
|
+
apiVersion: this.getApiVersion(),
|
|
789
|
+
fullDeviceType: this.getFullDeviceType()
|
|
720
790
|
};
|
|
721
791
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
const listConfig = this.buildList();
|
|
731
|
-
if (!fs.existsSync(listsPath)) return fs.writeFileSync(listsPath, JSON.stringify([listConfig], null, 2));
|
|
732
|
-
const lists = JSON.parse(fs.readFileSync(listsPath, "utf-8")) ?? [];
|
|
733
|
-
if (!Array.isArray(lists)) throw new DeployError(DeployError.Code.LIST_JSON_NOT_AN_ARRAY, "Lists is not an array");
|
|
734
|
-
if (lists.find((item) => item.name === listConfig.name)) throw new DeployError(DeployError.Code.DEVICE_ALREADY_DEPLOYED, `Image ${listConfig.name} already deployed in lists.json`);
|
|
735
|
-
lists.push(listConfig);
|
|
736
|
-
fs.mkdirSync(listConfig.path, { recursive: true });
|
|
737
|
-
fs.writeFileSync(path.join(listConfig.path, "config.ini"), this.toIniString());
|
|
738
|
-
fs.writeFileSync(path.join(deployedPath, `${this.options.name}.ini`), this.buildDeviceIniString());
|
|
739
|
-
fs.writeFileSync(listsPath, JSON.stringify(lists, null, 2));
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
//#endregion
|
|
795
|
+
//#region src/images/local-image.ts
|
|
796
|
+
let LocalImage;
|
|
797
|
+
(function(_LocalImage) {
|
|
798
|
+
function is(value) {
|
|
799
|
+
return value instanceof LocalImageImpl;
|
|
740
800
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
801
|
+
_LocalImage.is = is;
|
|
802
|
+
})(LocalImage || (LocalImage = {}));
|
|
803
|
+
var LocalImageImpl = class extends BaseImageImpl {
|
|
804
|
+
imageType = "local";
|
|
805
|
+
constructor(imageManager, sdkPkgFile, infoFile) {
|
|
806
|
+
super({
|
|
807
|
+
imageManager,
|
|
808
|
+
apiVersion: Number.parseInt(sdkPkgFile?.data?.apiVersion ?? "0"),
|
|
809
|
+
relativePath: sdkPkgFile?.data?.path?.split(",").join("/")
|
|
810
|
+
});
|
|
811
|
+
this.imageManager = imageManager;
|
|
812
|
+
this.sdkPkgFile = sdkPkgFile;
|
|
813
|
+
this.infoFile = infoFile;
|
|
814
|
+
}
|
|
815
|
+
getSdkPkgFile() {
|
|
816
|
+
return this.sdkPkgFile;
|
|
817
|
+
}
|
|
818
|
+
getFullDeviceType() {
|
|
819
|
+
const name = this.getSdkPkgFile().data?.displayName?.split("-");
|
|
820
|
+
return name?.[name.length - 1];
|
|
821
|
+
}
|
|
822
|
+
async createDevice(options) {
|
|
823
|
+
const { deployedPath, imageBasePath, configPath, logPath, adapter: { join } } = this.getImageManager().getOptions();
|
|
824
|
+
const screen = new ScreenPresetImpl(options.screen);
|
|
825
|
+
const emulatorDeviceItem = screen.getEmulatorDeviceItem();
|
|
826
|
+
const productConfigItem = screen.getProductConfigItem();
|
|
827
|
+
const listsFile = await this.getImageManager().readListsFile();
|
|
828
|
+
const uuid = crypto.randomUUID();
|
|
829
|
+
const deviceFolderPath = join(deployedPath, options.name);
|
|
830
|
+
const listFileItem = listsFile.addListsFileItem({
|
|
831
|
+
uuid,
|
|
832
|
+
"name": options.name,
|
|
833
|
+
"apiVersion": this.getApiVersion().toString(),
|
|
834
|
+
"cpuNumber": options.cpuNumber.toString(),
|
|
835
|
+
"path": deviceFolderPath.fsPath,
|
|
836
|
+
"memoryRamSize": options.memoryRamSize.toString(),
|
|
837
|
+
"dataDiskSize": options.dataDiskSize.toString(),
|
|
838
|
+
"version": this.getSdkPkgFile().data?.version ?? "",
|
|
839
|
+
"imageDir": this.getRelativePath(),
|
|
840
|
+
"showVersion": this.getSdkPkgFile().data?.guestVersion ?? "",
|
|
841
|
+
"harmonyos.sdk.path": imageBasePath.fsPath,
|
|
842
|
+
"harmonyos.config.path": configPath.fsPath,
|
|
843
|
+
"harmonyos.log.path": logPath.fsPath,
|
|
844
|
+
"hw.apiName": this.getSdkPkgFile().data?.platformVersion ?? "",
|
|
845
|
+
"abi": this.infoFile.abi,
|
|
846
|
+
"harmonyOSVersion": `${this.getSdkPkgFile().data?.guestVersion?.split(" ")[0]}-${this.getSdkPkgFile().data?.platformVersion}`,
|
|
847
|
+
"guestVersion": this.getSdkPkgFile().data?.guestVersion ?? "",
|
|
848
|
+
"diagonalSize": emulatorDeviceItem.getContent().diagonalSize.toString(),
|
|
849
|
+
"density": emulatorDeviceItem.getContent().density.toString(),
|
|
850
|
+
"resolutionWidth": emulatorDeviceItem.getContent().resolutionWidth.toString(),
|
|
851
|
+
"resolutionHeight": emulatorDeviceItem.getContent().resolutionHeight.toString(),
|
|
852
|
+
"coverResolutionWidth": EmulatorFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().coverResolutionWidth.toString() : void 0,
|
|
853
|
+
"coverResolutionHeight": EmulatorFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().coverResolutionHeight.toString() : void 0,
|
|
854
|
+
"coverDiagonalSize": EmulatorFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().coverDiagonalSize.toString() : void 0,
|
|
855
|
+
"type": emulatorDeviceItem.getContent().deviceType,
|
|
856
|
+
"devModel": productConfigItem.getDevModel(),
|
|
857
|
+
"model": productConfigItem.getContent().name
|
|
858
|
+
});
|
|
859
|
+
const device = new DeviceImpl({
|
|
860
|
+
imageManager: this.getImageManager(),
|
|
861
|
+
listsFile,
|
|
862
|
+
listFileItem,
|
|
863
|
+
screen
|
|
864
|
+
});
|
|
865
|
+
const deviceIniFile = new ConfigIniFileImpl(device, ConfigIniFileImpl.getFileUri(device), {
|
|
866
|
+
"name": listFileItem.getContent().name,
|
|
867
|
+
"deviceType": listFileItem.getContent().type,
|
|
868
|
+
"deviceModel": listFileItem.getContent().devModel,
|
|
869
|
+
"productModel": listFileItem.getContent().model,
|
|
870
|
+
"vendorCountry": options.vendorCountry ?? "CN",
|
|
871
|
+
"uuid": listFileItem.getContent().uuid,
|
|
872
|
+
"configPath": listFileItem.getContent()["harmonyos.config.path"],
|
|
873
|
+
"logPath": listFileItem.getContent()["harmonyos.log.path"],
|
|
874
|
+
"sdkPath": listFileItem.getContent()["harmonyos.sdk.path"],
|
|
875
|
+
"imageSubPath": listFileItem.getContent().imageDir,
|
|
876
|
+
"instancePath": listFileItem.getContent().path,
|
|
877
|
+
"os.osVersion": `${this.getSdkPkgFile().data?.guestVersion?.split(" ")[0]} ${this.getSdkPkgFile().data?.platformVersion}(${this.getApiVersion()})`,
|
|
878
|
+
"os.apiVersion": this.getApiVersion().toString(),
|
|
879
|
+
"os.softwareVersion": this.getSdkPkgFile().data?.version ?? "",
|
|
880
|
+
"os.isPublic": options.isPublic ?? true ? "true" : "false",
|
|
881
|
+
"hw.cpu.arch": listFileItem.getContent().abi,
|
|
882
|
+
"hw.cpu.ncore": listFileItem.getContent().cpuNumber,
|
|
883
|
+
"hw.lcd.density": emulatorDeviceItem.getContent().density.toFixed(),
|
|
884
|
+
"hw.lcd.single.diagonalSize": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().singleDiagonalSize.toString() : void 0,
|
|
885
|
+
"hw.lcd.single.height": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().singleResolutionHeight.toString() : void 0,
|
|
886
|
+
"hw.lcd.single.width": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().singleResolutionWidth.toString() : void 0,
|
|
887
|
+
"hw.lcd.double.diagonalSize": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().doubleDiagonalSize.toString() : void 0,
|
|
888
|
+
"hw.lcd.double.height": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().doubleResolutionHeight.toString() : void 0,
|
|
889
|
+
"hw.lcd.double.width": EmulatorTripleFoldItem.is(emulatorDeviceItem) ? emulatorDeviceItem.getContent().doubleResolutionWidth.toString() : void 0,
|
|
890
|
+
"hw.lcd.phy.height": emulatorDeviceItem.getContent().physicalHeight.toString(),
|
|
891
|
+
"hw.lcd.phy.width": emulatorDeviceItem.getContent().physicalWidth.toString(),
|
|
892
|
+
"hw.lcd.number": EmulatorTripleFoldItem.is(emulatorDeviceItem) || EmulatorFoldItem.is(emulatorDeviceItem) ? "2" : "1",
|
|
893
|
+
"hw.ramSize": listFileItem.getContent().memoryRamSize,
|
|
894
|
+
"hw.dataPartitionSize": listFileItem.getContent().dataDiskSize,
|
|
895
|
+
"isCustomize": "true",
|
|
896
|
+
"hw.hdc.port": "notset"
|
|
897
|
+
});
|
|
898
|
+
device.setConfigIniFile(deviceIniFile);
|
|
899
|
+
const namedIniFile = new NamedIniFileImpl(device, NamedIniFileImpl.getFileUri(device), {
|
|
900
|
+
"hvd.ini.encoding": "UTF-8",
|
|
901
|
+
"path": listFileItem.getContent().path
|
|
902
|
+
});
|
|
903
|
+
device.setNamedIniFile(namedIniFile);
|
|
904
|
+
await namedIniFile.write();
|
|
905
|
+
await deviceIniFile.write();
|
|
906
|
+
await listsFile.write();
|
|
907
|
+
return device;
|
|
758
908
|
}
|
|
759
909
|
toJSON() {
|
|
760
910
|
return {
|
|
761
|
-
...
|
|
762
|
-
|
|
763
|
-
ini: this.buildIni()
|
|
911
|
+
...super.toJSON(),
|
|
912
|
+
sdkPkgFile: this.getSdkPkgFile()
|
|
764
913
|
};
|
|
765
914
|
}
|
|
766
915
|
};
|
|
767
|
-
function createDevice(image, options) {
|
|
768
|
-
return new DeviceImpl(image, options);
|
|
769
|
-
}
|
|
770
916
|
|
|
771
917
|
//#endregion
|
|
772
|
-
//#region src/
|
|
773
|
-
var
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
this.
|
|
918
|
+
//#region src/errors/request-error.ts
|
|
919
|
+
var RemoteImageRequestError = class extends Error {
|
|
920
|
+
constructor(message, code, cause) {
|
|
921
|
+
super(message, { cause });
|
|
922
|
+
this.message = message;
|
|
923
|
+
this.code = code;
|
|
924
|
+
this.cause = cause;
|
|
778
925
|
}
|
|
779
|
-
|
|
780
|
-
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
//#endregion
|
|
929
|
+
//#region src/event-emitter.ts
|
|
930
|
+
var EventEmitter = class {
|
|
931
|
+
_listeners = [];
|
|
932
|
+
/**
|
|
933
|
+
* The event listeners can subscribe to.
|
|
934
|
+
*/
|
|
935
|
+
event = (listener, thisArgs, disposables) => {
|
|
936
|
+
this._listeners.push([
|
|
937
|
+
listener,
|
|
938
|
+
thisArgs,
|
|
939
|
+
disposables
|
|
940
|
+
]);
|
|
941
|
+
return { dispose: () => {
|
|
942
|
+
this._listeners = this._listeners.filter((l) => l[0] !== listener && l[1] !== thisArgs && l[2] !== disposables);
|
|
943
|
+
disposables?.forEach((disposable) => disposable.dispose());
|
|
944
|
+
} };
|
|
945
|
+
};
|
|
946
|
+
/**
|
|
947
|
+
* Notify all subscribers of the {@link EventEmitter.event event}. Failure
|
|
948
|
+
* of one or more listener will not fail this function call.
|
|
949
|
+
*
|
|
950
|
+
* @param data The event object.
|
|
951
|
+
*/
|
|
952
|
+
fire(data) {
|
|
953
|
+
this._listeners.forEach((listener) => {
|
|
954
|
+
if (listener[1] !== void 0) listener[1].call(listener[2], data);
|
|
955
|
+
else listener[0](data);
|
|
956
|
+
});
|
|
781
957
|
}
|
|
782
|
-
|
|
783
|
-
|
|
958
|
+
/**
|
|
959
|
+
* Dispose this object and free resources.
|
|
960
|
+
*/
|
|
961
|
+
dispose() {
|
|
962
|
+
this._listeners.forEach((listener) => listener[2]?.forEach((disposable) => disposable.dispose()));
|
|
963
|
+
this._listeners = [];
|
|
784
964
|
}
|
|
785
|
-
|
|
786
|
-
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
//#endregion
|
|
968
|
+
//#region src/image-downloader.ts
|
|
969
|
+
var ImageDownloaderImpl = class {
|
|
970
|
+
constructor(remoteImage, url, abortController = new AbortController()) {
|
|
971
|
+
this.remoteImage = remoteImage;
|
|
787
972
|
this.url = url;
|
|
973
|
+
this.abortController = abortController;
|
|
788
974
|
}
|
|
789
|
-
|
|
790
|
-
|
|
975
|
+
downloadProgressEmitter = new EventEmitter();
|
|
976
|
+
extractProgressEmitter = new EventEmitter();
|
|
977
|
+
checksumProgressEmitter = new EventEmitter();
|
|
978
|
+
onDownloadProgress = this.downloadProgressEmitter.event;
|
|
979
|
+
onExtractProgress = this.extractProgressEmitter.event;
|
|
980
|
+
onChecksumProgress = this.checksumProgressEmitter.event;
|
|
981
|
+
getRemoteImage() {
|
|
982
|
+
return this.remoteImage;
|
|
791
983
|
}
|
|
792
984
|
getUrl() {
|
|
793
985
|
return this.url;
|
|
794
986
|
}
|
|
795
|
-
|
|
796
|
-
const {
|
|
797
|
-
return
|
|
987
|
+
getCacheUri() {
|
|
988
|
+
const { cachePath, adapter: { URI, join, basename } } = this.remoteImage.getImageManager().getOptions();
|
|
989
|
+
return join(cachePath, basename(URI.parse(this.url)));
|
|
798
990
|
}
|
|
799
|
-
async makeRequest(
|
|
800
|
-
const { fs } = this.
|
|
801
|
-
const
|
|
802
|
-
const transformProgress = this.createProgressTransformer(startByte);
|
|
991
|
+
async makeRequest(startByte = 0, retried416 = false) {
|
|
992
|
+
const { adapter: { fs, axios, isAxiosError } } = this.remoteImage.getImageManager().getOptions();
|
|
993
|
+
const cacheUri = this.getCacheUri();
|
|
803
994
|
try {
|
|
804
995
|
return await axios.get(this.url, {
|
|
805
996
|
headers: startByte > 0 ? { Range: `bytes=${startByte}-` } : {},
|
|
806
997
|
responseType: "stream",
|
|
807
998
|
validateStatus: (status) => status === 200 || status === 206,
|
|
808
|
-
|
|
809
|
-
signal
|
|
999
|
+
signal: this.abortController.signal
|
|
810
1000
|
});
|
|
811
1001
|
} catch (err) {
|
|
812
|
-
if (err
|
|
813
|
-
if (fs.
|
|
814
|
-
return this.makeRequest(
|
|
1002
|
+
if (isAxiosError(err) && err.response?.status === 416 && !retried416) {
|
|
1003
|
+
if (await fs.exists(cacheUri)) await fs.delete(cacheUri, { recursive: true });
|
|
1004
|
+
return this.makeRequest(startByte, true);
|
|
815
1005
|
}
|
|
816
1006
|
throw err;
|
|
817
1007
|
}
|
|
818
1008
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
const
|
|
822
|
-
if (
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
const
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
const
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
1009
|
+
/** 获取文件总大小。206 时从 Content-Range 取 total,200 时从 Content-Length 取。 */
|
|
1010
|
+
parseTotalBytes(response) {
|
|
1011
|
+
const contentRange = response.headers["content-range"];
|
|
1012
|
+
if (contentRange) {
|
|
1013
|
+
const match = contentRange.match(/bytes \d+-\d+\/(\d+)/);
|
|
1014
|
+
if (match) return Number.parseInt(match[1], 10);
|
|
1015
|
+
}
|
|
1016
|
+
const contentLength = response.headers["content-length"];
|
|
1017
|
+
if (contentLength) return Number.parseInt(contentLength, 10);
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
createDownloadProgressTransformer(startByte, totalBytes) {
|
|
1021
|
+
let receivedBytes = startByte;
|
|
1022
|
+
let lastReportedBytes = startByte;
|
|
1023
|
+
let lastReportedProgress = totalBytes != null && totalBytes > 0 ? Math.round(startByte / totalBytes * 1e4) / 100 : 0;
|
|
1024
|
+
let lastReportTime = performance.now();
|
|
1025
|
+
const reportThreshold = 64 * 1024;
|
|
1026
|
+
const report = () => {
|
|
1027
|
+
const now = performance.now();
|
|
1028
|
+
const bytesSinceLastReport = receivedBytes - lastReportedBytes;
|
|
1029
|
+
const timeDeltaSec = (now - lastReportTime) / 1e3;
|
|
1030
|
+
lastReportedBytes = receivedBytes;
|
|
1031
|
+
lastReportTime = now;
|
|
1032
|
+
const progress = totalBytes != null && totalBytes > 0 ? Math.min(100, Math.round(receivedBytes / totalBytes * 1e4) / 100) : 0;
|
|
1033
|
+
const increment = Math.round((progress - lastReportedProgress) * 100) / 100;
|
|
1034
|
+
lastReportedProgress = progress;
|
|
1035
|
+
const speedKBps = timeDeltaSec > 0 && bytesSinceLastReport > 0 ? bytesSinceLastReport / 1024 / timeDeltaSec : 0;
|
|
1036
|
+
const unit = speedKBps >= 1024 ? "MB" : "KB";
|
|
1037
|
+
const network = unit === "MB" ? speedKBps / 1024 : speedKBps;
|
|
1038
|
+
const roundedProgress = Math.round(progress * 100) / 100;
|
|
1039
|
+
const clampedIncrement = Math.max(0, Math.min(100, increment));
|
|
1040
|
+
if (clampedIncrement > 0) this.downloadProgressEmitter.fire({
|
|
1041
|
+
progressType: "download",
|
|
1042
|
+
increment: clampedIncrement,
|
|
1043
|
+
progress: roundedProgress,
|
|
1044
|
+
network: Math.round(network * 100) / 100,
|
|
1045
|
+
unit
|
|
1046
|
+
});
|
|
1047
|
+
};
|
|
1048
|
+
return new TransformStream({
|
|
1049
|
+
transform: (chunk, controller) => {
|
|
1050
|
+
receivedBytes += chunk.length;
|
|
1051
|
+
controller.enqueue(chunk);
|
|
1052
|
+
if (receivedBytes - lastReportedBytes >= reportThreshold) report();
|
|
1053
|
+
},
|
|
1054
|
+
flush: () => {
|
|
1055
|
+
if (receivedBytes !== lastReportedBytes) report();
|
|
1056
|
+
}
|
|
852
1057
|
});
|
|
853
1058
|
}
|
|
854
|
-
async
|
|
855
|
-
const {
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
const
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
stream.pipe(progressStream).pipe(extractStream);
|
|
872
|
-
await extractStream.promise();
|
|
873
|
-
if (symlinkOpenHarmonySdk) {
|
|
874
|
-
const symlinkSdkPath = path.resolve(imageBasePath, "default", "openharmony");
|
|
875
|
-
if (!fs.existsSync(path.dirname(symlinkSdkPath))) fs.mkdirSync(path.dirname(symlinkSdkPath), { recursive: true });
|
|
876
|
-
if (!fs.existsSync(symlinkSdkPath)) fs.symlinkSync(sdkPath, symlinkSdkPath, "dir");
|
|
1059
|
+
async startDownload(retried416 = false) {
|
|
1060
|
+
const { adapter: { fs, toWeb, dirname } } = this.remoteImage.getImageManager().getOptions();
|
|
1061
|
+
const cacheUri = this.getCacheUri();
|
|
1062
|
+
if (!await fs.exists(dirname(cacheUri))) await fs.createDirectory(dirname(cacheUri));
|
|
1063
|
+
const startByte = await fs.stat(cacheUri).then((stat) => stat.size ?? 0, () => 0);
|
|
1064
|
+
const response = await this.makeRequest(startByte, retried416);
|
|
1065
|
+
const totalBytes = this.parseTotalBytes(response);
|
|
1066
|
+
if (startByte > 0 && totalBytes != null && totalBytes > 0) {
|
|
1067
|
+
const startProgress = Math.round(startByte / totalBytes * 1e4) / 100;
|
|
1068
|
+
this.downloadProgressEmitter.fire({
|
|
1069
|
+
progressType: "download",
|
|
1070
|
+
increment: 0,
|
|
1071
|
+
progress: Math.min(100, startProgress),
|
|
1072
|
+
network: 0,
|
|
1073
|
+
unit: "KB",
|
|
1074
|
+
reset: true
|
|
1075
|
+
});
|
|
877
1076
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
let
|
|
886
|
-
|
|
887
|
-
const
|
|
888
|
-
|
|
889
|
-
const
|
|
890
|
-
const
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
return {
|
|
900
|
-
...progress,
|
|
901
|
-
total,
|
|
902
|
-
loaded,
|
|
903
|
-
network,
|
|
904
|
-
unit,
|
|
905
|
-
increment
|
|
906
|
-
};
|
|
1077
|
+
const writableStream = await fs.createWritableStream(cacheUri, startByte > 0 ? { flags: WriteableFlags.Append } : void 0);
|
|
1078
|
+
const webReadable = toWeb(response.data);
|
|
1079
|
+
const progressTransform = this.createDownloadProgressTransformer(startByte, totalBytes);
|
|
1080
|
+
await webReadable.pipeThrough(progressTransform).pipeTo(writableStream);
|
|
1081
|
+
}
|
|
1082
|
+
createChecksumProgressTransformer(totalBytes, hash) {
|
|
1083
|
+
let readBytes = 0;
|
|
1084
|
+
let lastReportedBytes = 0;
|
|
1085
|
+
let lastReportedProgress = 0;
|
|
1086
|
+
const reportThreshold = 64 * 1024;
|
|
1087
|
+
const report = () => {
|
|
1088
|
+
const progress = totalBytes > 0 ? Math.min(100, Math.round(readBytes / totalBytes * 1e4) / 100) : 0;
|
|
1089
|
+
const increment = Math.round((progress - lastReportedProgress) * 100) / 100;
|
|
1090
|
+
lastReportedBytes = readBytes;
|
|
1091
|
+
lastReportedProgress = progress;
|
|
1092
|
+
const clampedIncrement = Math.max(0, Math.min(100, increment));
|
|
1093
|
+
if (clampedIncrement > 0) this.checksumProgressEmitter.fire({
|
|
1094
|
+
progressType: "checksum",
|
|
1095
|
+
increment: clampedIncrement,
|
|
1096
|
+
progress: Math.round(progress * 100) / 100
|
|
1097
|
+
});
|
|
907
1098
|
};
|
|
1099
|
+
return new TransformStream({
|
|
1100
|
+
transform: (chunk, controller) => {
|
|
1101
|
+
const chunkLength = chunk ? chunk.byteLength ?? chunk.length ?? 0 : 0;
|
|
1102
|
+
if (chunk) hash.update(chunk);
|
|
1103
|
+
readBytes += chunkLength;
|
|
1104
|
+
controller.enqueue(chunk);
|
|
1105
|
+
if (readBytes - lastReportedBytes >= reportThreshold) report();
|
|
1106
|
+
},
|
|
1107
|
+
flush: () => {
|
|
1108
|
+
if (readBytes !== lastReportedBytes) report();
|
|
1109
|
+
}
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
async checkChecksum() {
|
|
1113
|
+
const { adapter: { fs, crypto } } = this.remoteImage.getImageManager().getOptions();
|
|
1114
|
+
const cacheUri = this.getCacheUri();
|
|
1115
|
+
const totalBytes = await fs.stat(cacheUri).then((stat) => stat.size ?? 0, () => 0);
|
|
1116
|
+
const readableStream = await fs.createReadableStream(cacheUri);
|
|
1117
|
+
const hash = crypto.createHash("sha256");
|
|
1118
|
+
const progressTransform = this.createChecksumProgressTransformer(totalBytes, hash);
|
|
1119
|
+
await readableStream.pipeThrough(progressTransform).pipeTo(new WritableStream(), { signal: this.abortController.signal });
|
|
1120
|
+
return hash.digest("hex") === this.getRemoteImage().getRemoteImageSDK().archive?.complete?.checksum;
|
|
1121
|
+
}
|
|
1122
|
+
async extract() {
|
|
1123
|
+
const { adapter: { fs, unzipper, fromWeb } } = this.remoteImage.getImageManager().getOptions();
|
|
1124
|
+
const cacheUri = this.getCacheUri();
|
|
1125
|
+
const totalBytes = await fs.stat(cacheUri).then((stat) => stat.size ?? 0, () => 0);
|
|
1126
|
+
const extract = unzipper.Extract({ path: this.getRemoteImage().getFullPath().fsPath });
|
|
1127
|
+
const webReadable = await fs.createReadableStream(cacheUri);
|
|
1128
|
+
let readBytes = 0;
|
|
1129
|
+
let lastReportedBytes = 0;
|
|
1130
|
+
let lastReportedProgress = 0;
|
|
1131
|
+
const reportThreshold = 64 * 1024;
|
|
1132
|
+
const copyAndProgressTransform = new TransformStream({
|
|
1133
|
+
transform: (chunk, controller) => {
|
|
1134
|
+
const chunkLength = chunk?.length ?? 0;
|
|
1135
|
+
if (chunkLength <= 0) return;
|
|
1136
|
+
readBytes += chunkLength;
|
|
1137
|
+
if (readBytes - lastReportedBytes >= reportThreshold) {
|
|
1138
|
+
const progress = totalBytes > 0 ? Math.min(100, Math.round(readBytes / totalBytes * 1e4) / 100) : 0;
|
|
1139
|
+
const increment = Math.round((progress - lastReportedProgress) * 100) / 100;
|
|
1140
|
+
lastReportedBytes = readBytes;
|
|
1141
|
+
lastReportedProgress = progress;
|
|
1142
|
+
const clampedIncrement = Math.max(0, Math.min(100, increment));
|
|
1143
|
+
if (clampedIncrement > 0) this.extractProgressEmitter.fire({
|
|
1144
|
+
progressType: "extract",
|
|
1145
|
+
increment: clampedIncrement,
|
|
1146
|
+
progress: Math.round(progress * 100) / 100
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
controller.enqueue(chunk.slice(0));
|
|
1150
|
+
},
|
|
1151
|
+
flush: () => {
|
|
1152
|
+
if (readBytes !== lastReportedBytes) {
|
|
1153
|
+
const increment = Math.round((100 - lastReportedProgress) * 100) / 100;
|
|
1154
|
+
const clampedIncrement = Math.max(0, Math.min(100, increment));
|
|
1155
|
+
if (clampedIncrement > 0) this.extractProgressEmitter.fire({
|
|
1156
|
+
progressType: "extract",
|
|
1157
|
+
increment: clampedIncrement,
|
|
1158
|
+
progress: 100
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
});
|
|
1163
|
+
const readable = fromWeb(webReadable.pipeThrough(copyAndProgressTransform));
|
|
1164
|
+
const abortHandler = () => readable.destroy(new DOMException("Aborted", "AbortError"));
|
|
1165
|
+
this.abortController.signal.addEventListener("abort", abortHandler);
|
|
1166
|
+
readable.pipe(extract);
|
|
1167
|
+
await extract.promise().finally(() => this.abortController.signal.removeEventListener("abort", abortHandler));
|
|
908
1168
|
}
|
|
909
1169
|
};
|
|
910
|
-
function createImageDownloader(image, url) {
|
|
911
|
-
return new ImageDownloaderImpl(image, url);
|
|
912
|
-
}
|
|
913
1170
|
|
|
914
1171
|
//#endregion
|
|
915
|
-
//#region src/images/image.ts
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
this.resolvedFsPath = resolvedFsPath;
|
|
921
|
-
}
|
|
922
|
-
getImageManager() {
|
|
923
|
-
return this.imageManager;
|
|
924
|
-
}
|
|
925
|
-
getArch() {
|
|
926
|
-
const [, , deviceTypeWithArch] = this.getPath()?.split(",") ?? [];
|
|
927
|
-
const split = deviceTypeWithArch?.split("_") ?? [];
|
|
928
|
-
return split[split.length - 1];
|
|
929
|
-
}
|
|
930
|
-
getPath() {
|
|
931
|
-
return this.response?.path;
|
|
932
|
-
}
|
|
933
|
-
getChecksum() {
|
|
934
|
-
return this.response?.archive?.complete?.checksum;
|
|
935
|
-
}
|
|
936
|
-
getReleaseType() {
|
|
937
|
-
return this.response?.releaseType;
|
|
938
|
-
}
|
|
939
|
-
getFsPath() {
|
|
940
|
-
return this.resolvedFsPath;
|
|
941
|
-
}
|
|
942
|
-
async isDownloaded() {
|
|
943
|
-
return this.imageManager.getOptions().fs.existsSync(this.getFsPath()) && this.imageManager.getOptions().fs.statSync(this.getFsPath()).isDirectory();
|
|
944
|
-
}
|
|
945
|
-
getVersion() {
|
|
946
|
-
return this.response?.version;
|
|
947
|
-
}
|
|
948
|
-
getApiVersion() {
|
|
949
|
-
return this.response?.apiVersion;
|
|
950
|
-
}
|
|
951
|
-
getTargetOS() {
|
|
952
|
-
const [, systemNameWithVersion] = this.getPath()?.split(",") ?? [];
|
|
953
|
-
const [systemName] = systemNameWithVersion?.split("-") ?? [];
|
|
954
|
-
return systemName ?? "";
|
|
1172
|
+
//#region src/images/remote-image.ts
|
|
1173
|
+
let RemoteImage;
|
|
1174
|
+
(function(_RemoteImage) {
|
|
1175
|
+
function is(value) {
|
|
1176
|
+
return value instanceof RemoteImageImpl;
|
|
955
1177
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1178
|
+
_RemoteImage.is = is;
|
|
1179
|
+
})(RemoteImage || (RemoteImage = {}));
|
|
1180
|
+
var RemoteImageImpl = class extends BaseImageImpl {
|
|
1181
|
+
imageType = "remote";
|
|
1182
|
+
constructor(imageManager, remoteImageSDK = {}) {
|
|
1183
|
+
super({
|
|
1184
|
+
imageManager,
|
|
1185
|
+
relativePath: remoteImageSDK.path?.split(",").join("/") ?? "",
|
|
1186
|
+
apiVersion: remoteImageSDK.apiVersion ? Number.parseInt(remoteImageSDK.apiVersion) : 0
|
|
1187
|
+
});
|
|
1188
|
+
this.imageManager = imageManager;
|
|
1189
|
+
this.remoteImageSDK = remoteImageSDK;
|
|
960
1190
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
const [deviceType] = deviceTypeWithArch?.split("_") ?? [];
|
|
964
|
-
return deviceType ?? "";
|
|
1191
|
+
getRemoteImageSDK() {
|
|
1192
|
+
return this.remoteImageSDK;
|
|
965
1193
|
}
|
|
966
|
-
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
return deviceType.toLowerCase();
|
|
1194
|
+
getFullDeviceType() {
|
|
1195
|
+
const name = this.getRemoteImageSDK().displayName?.split("-");
|
|
1196
|
+
return name?.[name.length - 1];
|
|
970
1197
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
if (
|
|
974
|
-
|
|
1198
|
+
_localImage;
|
|
1199
|
+
async getLocalImage(force = false) {
|
|
1200
|
+
if (!force && this._localImage) return this._localImage;
|
|
1201
|
+
this._localImage = (await this.getImageManager().getLocalImages()).find((localImage) => localImage.getFullPath().toString() === this.getFullPath().toString());
|
|
1202
|
+
return this._localImage;
|
|
975
1203
|
}
|
|
976
|
-
async
|
|
1204
|
+
async createDownloader(signals) {
|
|
1205
|
+
const { adapter: { axios, isAxiosError } } = this.imageManager.getOptions();
|
|
977
1206
|
try {
|
|
978
1207
|
const response = await axios.post("https://devecostudio-drcn.deveco.dbankcloud.com/sdkmanager/v7/hos/download", {
|
|
979
|
-
osArch: this.
|
|
980
|
-
osType: this.
|
|
1208
|
+
osArch: this.getImageManager().getArch(),
|
|
1209
|
+
osType: this.getImageManager().getOperatingSystem(),
|
|
981
1210
|
path: {
|
|
982
|
-
path: this.
|
|
983
|
-
version: this.
|
|
1211
|
+
path: this.getRemoteImageSDK().path,
|
|
1212
|
+
version: this.getRemoteImageSDK().version
|
|
984
1213
|
},
|
|
985
1214
|
imei: "d490a470-8719-4baf-9cc4-9c78d40d"
|
|
986
1215
|
});
|
|
987
|
-
if (typeof response.data?.url !== "string")
|
|
988
|
-
return response.data.url;
|
|
1216
|
+
if (typeof response.data?.url !== "string") throw new RemoteImageRequestError(response.data?.body, response.data?.code);
|
|
1217
|
+
return new ImageDownloaderImpl(this, response.data.url, signals);
|
|
989
1218
|
} catch (error) {
|
|
990
|
-
|
|
1219
|
+
if (isAxiosError(error)) throw new RemoteImageRequestError(error.message, Number(error.code), error);
|
|
1220
|
+
if (error instanceof Error) throw new RemoteImageRequestError(error.message, -1, error);
|
|
1221
|
+
throw new RemoteImageRequestError("Unknown request error.", -1, error);
|
|
991
1222
|
}
|
|
992
1223
|
}
|
|
993
1224
|
toJSON() {
|
|
994
1225
|
return {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
path: this.getPath(),
|
|
998
|
-
checksum: this.getChecksum(),
|
|
999
|
-
fsPath: this.getFsPath(),
|
|
1000
|
-
version: this.getVersion(),
|
|
1001
|
-
apiVersion: this.getApiVersion(),
|
|
1002
|
-
targetOS: this.getTargetOS(),
|
|
1003
|
-
targetVersion: this.getTargetVersion(),
|
|
1004
|
-
deviceType: this.getDeviceType(),
|
|
1005
|
-
snakecaseDeviceType: this.getSnakecaseDeviceType()
|
|
1226
|
+
...super.toJSON(),
|
|
1227
|
+
remoteImageSDK: this.getRemoteImageSDK()
|
|
1006
1228
|
};
|
|
1007
1229
|
}
|
|
1008
1230
|
};
|
|
1009
1231
|
|
|
1010
1232
|
//#endregion
|
|
1011
|
-
//#region src/
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
"
|
|
1023
|
-
"
|
|
1024
|
-
"
|
|
1025
|
-
"
|
|
1026
|
-
"
|
|
1027
|
-
"
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
async getProductConfig(usingDefaultProductConfig = false) {
|
|
1035
|
-
const productConfig = usingDefaultProductConfig ? (await import("./default-product-config.mjs")).default : await this.getImageManager().getProductConfig();
|
|
1036
|
-
const deviceType = this.getDeviceType().toLowerCase();
|
|
1037
|
-
if (!deviceType) return [];
|
|
1038
|
-
if (deviceType === "pc") return productConfig["2in1 Foldable"] ?? [];
|
|
1039
|
-
const key = Object.keys(productConfig).find((key) => key.toLowerCase() === deviceType);
|
|
1040
|
-
if (key) return productConfig[key] ?? [];
|
|
1041
|
-
return [];
|
|
1042
|
-
}
|
|
1043
|
-
async delete() {
|
|
1044
|
-
const { fs } = this.getImageManager().getOptions();
|
|
1045
|
-
const path = this.getFsPath();
|
|
1046
|
-
if (!fs.existsSync(path) || !fs.statSync(path).isDirectory()) return /* @__PURE__ */ new Error("Image path does not exist");
|
|
1047
|
-
fs.rmSync(path, { recursive: true });
|
|
1048
|
-
const devices = await this.getDevices();
|
|
1049
|
-
const error = await Promise.allSettled(devices.map((device) => device.delete())).then((results) => results.find((result) => result.status === "rejected"));
|
|
1050
|
-
if (error) return error.reason;
|
|
1051
|
-
}
|
|
1052
|
-
getExecutablePath() {
|
|
1053
|
-
const { emulatorPath, process, path } = this.getImageManager().getOptions();
|
|
1054
|
-
return process.platform === "win32" ? path.join(emulatorPath, "Emulator.exe") : path.join(emulatorPath, "Emulator");
|
|
1055
|
-
}
|
|
1056
|
-
async buildStartCommand(device) {
|
|
1057
|
-
const config = device.buildList();
|
|
1058
|
-
return `${this.getExecutablePath()} ${[
|
|
1059
|
-
"-hvd",
|
|
1060
|
-
`"${config.name.replace(/"/g, "\\\"")}"`,
|
|
1061
|
-
"-path",
|
|
1062
|
-
`"${this.getImageManager().getOptions().deployedPath.replace(/"/g, "\\\"")}"`,
|
|
1063
|
-
"-imageRoot",
|
|
1064
|
-
`"${this.getImageManager().getOptions().imageBasePath.replace(/"/g, "\\\"")}"`
|
|
1065
|
-
].join(" ")}`;
|
|
1066
|
-
}
|
|
1067
|
-
async start(deployer) {
|
|
1068
|
-
const { child_process, emulatorPath } = this.getImageManager().getOptions();
|
|
1069
|
-
return child_process.exec(await this.buildStartCommand(deployer), { cwd: emulatorPath });
|
|
1070
|
-
}
|
|
1071
|
-
async buildStopCommand(device) {
|
|
1072
|
-
const config = device.buildList();
|
|
1073
|
-
return `${this.getExecutablePath()} ${["-stop", `"${config.name.replace(/"/g, "\\\"")}"`].join(" ")}`;
|
|
1074
|
-
}
|
|
1075
|
-
async stop(device) {
|
|
1076
|
-
const { child_process, emulatorPath } = this.getImageManager().getOptions();
|
|
1077
|
-
return child_process.exec(await this.buildStopCommand(device), { cwd: emulatorPath });
|
|
1078
|
-
}
|
|
1079
|
-
async createScreenLike(listsJsonItem) {
|
|
1080
|
-
const productConfig = await this.getImageManager().getProductConfig();
|
|
1081
|
-
const pascalCaseDeviceType = await this.getPascalCaseDeviceType();
|
|
1082
|
-
const screen = createScreen({
|
|
1083
|
-
diagonal: Number(listsJsonItem.diagonalSize),
|
|
1084
|
-
height: Number(listsJsonItem.resolutionHeight),
|
|
1085
|
-
width: Number(listsJsonItem.resolutionWidth),
|
|
1086
|
-
density: Number(listsJsonItem.density),
|
|
1087
|
-
deviceType: listsJsonItem.type,
|
|
1088
|
-
apiVersion: Number(listsJsonItem.apiVersion),
|
|
1089
|
-
cover: listsJsonItem.coverResolutionWidth && listsJsonItem.coverResolutionHeight && listsJsonItem.coverDiagonalSize ? {
|
|
1090
|
-
height: Number(listsJsonItem.coverResolutionHeight),
|
|
1091
|
-
width: Number(listsJsonItem.coverResolutionWidth),
|
|
1092
|
-
diagonal: Number(listsJsonItem.coverDiagonalSize)
|
|
1093
|
-
} : void 0
|
|
1094
|
-
});
|
|
1095
|
-
if (pascalCaseDeviceType) {
|
|
1096
|
-
const productConfigItem = productConfig[pascalCaseDeviceType]?.find((item) => item.name === listsJsonItem.model);
|
|
1097
|
-
if (productConfigItem && productConfigItem.outerScreenWidth && productConfigItem.outerScreenHeight && productConfigItem.outerScreenDiagonal) screen.setOuterScreen(createOuterScreen({
|
|
1098
|
-
width: Number(productConfigItem.outerScreenWidth),
|
|
1099
|
-
height: Number(productConfigItem.outerScreenHeight),
|
|
1100
|
-
diagonal: Number(productConfigItem.outerScreenDiagonal)
|
|
1101
|
-
}, screen));
|
|
1102
|
-
if (productConfigItem && productConfigItem.outerDoubleScreenWidth && productConfigItem.outerDoubleScreenHeight && productConfigItem.outerDoubleScreenDiagonal) screen.getOuterScreen()?.setOuterDoubleScreen(createOuterDoubleScreen({
|
|
1103
|
-
width: Number(productConfigItem.outerDoubleScreenWidth),
|
|
1104
|
-
height: Number(productConfigItem.outerDoubleScreenHeight),
|
|
1105
|
-
diagonal: Number(productConfigItem.outerDoubleScreenDiagonal)
|
|
1106
|
-
}, screen.getOuterScreen()));
|
|
1233
|
+
//#region src/options.ts
|
|
1234
|
+
let OptionsResolver;
|
|
1235
|
+
(function(_OptionsResolver) {
|
|
1236
|
+
async function resolveAdapter(adapter) {
|
|
1237
|
+
const mergedAdapter = {
|
|
1238
|
+
os: adapter?.os ?? await import("node:os"),
|
|
1239
|
+
process: adapter?.process ?? await import("node:process"),
|
|
1240
|
+
crypto: adapter?.crypto ?? await import("node:crypto"),
|
|
1241
|
+
child_process: adapter?.child_process ?? await import("node:child_process"),
|
|
1242
|
+
axios: adapter?.axios ?? (await import("axios")).default,
|
|
1243
|
+
fs: adapter?.fs ?? await createNodeFileSystem(),
|
|
1244
|
+
join: adapter?.join ?? (await import("vscode-uri")).Utils.joinPath,
|
|
1245
|
+
URI: adapter?.URI ?? (await import("vscode-uri")).URI,
|
|
1246
|
+
dirname: adapter?.dirname ?? (await import("vscode-uri")).Utils.dirname,
|
|
1247
|
+
basename: adapter?.basename ?? (await import("vscode-uri")).Utils.basename,
|
|
1248
|
+
toWeb: adapter?.toWeb ?? (await import("node:stream")).Readable.toWeb,
|
|
1249
|
+
fromWeb: adapter?.fromWeb ?? (await import("node:stream")).Readable.fromWeb,
|
|
1250
|
+
unzipper: adapter?.unzipper ?? await import("unzipper")
|
|
1251
|
+
};
|
|
1252
|
+
if (adapter?.isAxiosError) mergedAdapter.isAxiosError = adapter.isAxiosError;
|
|
1253
|
+
else {
|
|
1254
|
+
const axios = await import("axios");
|
|
1255
|
+
mergedAdapter.isAxiosError = (error) => axios.isAxiosError(error);
|
|
1107
1256
|
}
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const listsJson = JSON.parse(fs.readFileSync(listsJsonPath, "utf-8"));
|
|
1121
|
-
if (!Array.isArray(listsJson) || this.imageType !== "local") return [];
|
|
1122
|
-
const devices = [];
|
|
1123
|
-
for (const listsJsonItem of listsJson) {
|
|
1124
|
-
if (path.resolve(imageBasePath, listsJsonItem.imageDir) !== this.getFsPath()) continue;
|
|
1125
|
-
const iniFilePath = path.resolve(listsJsonItem.path, "config.ini");
|
|
1126
|
-
if (!fs.existsSync(iniFilePath) || !fs.statSync(iniFilePath).isFile()) continue;
|
|
1127
|
-
const device = this.createDevice({
|
|
1128
|
-
name: listsJsonItem.name,
|
|
1129
|
-
cpuNumber: Number(listsJsonItem.cpuNumber),
|
|
1130
|
-
diskSize: Number(listsJsonItem.dataDiskSize),
|
|
1131
|
-
memorySize: Number(listsJsonItem.memoryRamSize),
|
|
1132
|
-
screen: await this.createScreenLike(listsJsonItem)
|
|
1133
|
-
});
|
|
1134
|
-
device.setUuid(listsJsonItem.uuid).setCachedList(listsJsonItem).setCachedIni(INI.parse(fs.readFileSync(iniFilePath, "utf-8")));
|
|
1135
|
-
if (!fs.existsSync(listsJsonItem.path) || !fs.statSync(listsJsonItem.path).isDirectory()) continue;
|
|
1136
|
-
devices.push(device);
|
|
1257
|
+
return mergedAdapter;
|
|
1258
|
+
}
|
|
1259
|
+
_OptionsResolver.resolveAdapter = resolveAdapter;
|
|
1260
|
+
async function resolveImageManagerOptions(options) {
|
|
1261
|
+
const adapter = await resolveAdapter(options.adapter);
|
|
1262
|
+
const { os, join, process, URI } = adapter;
|
|
1263
|
+
function resolveDefaultImageBasePath() {
|
|
1264
|
+
switch (process.platform) {
|
|
1265
|
+
case "win32": return typeof process.env.APPDATA === "string" && process.env.APPDATA.length > 0 ? join(URI.file(process.env.APPDATA), "Local", "Huawei", "Sdk") : join(URI.file(os.homedir()), "AppData", "Local", "Huawei", "Sdk");
|
|
1266
|
+
case "darwin": return join(URI.file(os.homedir()), "Library", "Huawei", "Sdk");
|
|
1267
|
+
default: return join(URI.file(os.homedir()), ".huawei", "Sdk");
|
|
1268
|
+
}
|
|
1137
1269
|
}
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1270
|
+
function resolveDefaultDeployedPath() {
|
|
1271
|
+
switch (process.platform) {
|
|
1272
|
+
case "win32": return typeof process.env.APPDATA === "string" && process.env.APPDATA.length > 0 ? join(URI.file(process.env.APPDATA), "Local", "Huawei", "Emulator", "deployed") : join(URI.file(os.homedir()), "AppData", "Local", "Huawei", "Emulator", "deployed");
|
|
1273
|
+
default: return join(URI.file(os.homedir()), ".huawei", "Emulator", "deployed");
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
function resolveDefaultSdkPath() {
|
|
1277
|
+
switch (process.platform) {
|
|
1278
|
+
case "darwin": return URI.file("/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony");
|
|
1279
|
+
case "win32": return URI.file("C:\\Program Files\\Huawei\\DevEco Studio\\sdk\\default\\openharmony");
|
|
1280
|
+
default: return join(URI.file(os.homedir()), ".huawei", "Sdk", "default", "openharmony");
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
function resolveDefaultConfigPath() {
|
|
1284
|
+
switch (process.platform) {
|
|
1285
|
+
case "darwin": return join(URI.file(os.homedir()), "Library", "Application Support", "Huawei", "DevEcoStudio6.0");
|
|
1286
|
+
case "win32": return join(URI.file(process.env.APPDATA ?? os.homedir()), "Roaming", "Huawei", "DevEcoStudio6.0");
|
|
1287
|
+
default: return join(URI.file(os.homedir()), ".huawei", "DevEcoStudio6.0");
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
function resolveDefaultLogPath() {
|
|
1291
|
+
switch (process.platform) {
|
|
1292
|
+
case "darwin": return join(URI.file(os.homedir()), "Library", "Logs", "Huawei", "DevEcoStudio6.0");
|
|
1293
|
+
case "win32": return join(URI.file(process.env.APPDATA ?? os.homedir()), "Local", "Huawei", "DevEcoStudio6.0", "log");
|
|
1294
|
+
default: return join(URI.file(os.homedir()), ".huawei", "DevEcoStudio6.0", "log");
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
function resolveDefaultEmulatorPath() {
|
|
1298
|
+
switch (process.platform) {
|
|
1299
|
+
case "darwin": return URI.file("/Applications/DevEco-Studio.app/Contents/tools/emulator");
|
|
1300
|
+
case "win32": return URI.file("C:\\Program Files\\Huawei\\DevEco Studio\\tools\\emulator");
|
|
1301
|
+
default: return join(URI.file(os.homedir()), ".huawei", "Emulator");
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
const imageBasePath = typeof options.imageBasePath === "string" ? URI.file(options.imageBasePath) : options.imageBasePath || resolveDefaultImageBasePath();
|
|
1305
|
+
const cachePath = typeof options.cachePath === "string" ? URI.file(options.cachePath) : options.cachePath || join(imageBasePath, "cache");
|
|
1141
1306
|
return {
|
|
1142
|
-
|
|
1143
|
-
|
|
1307
|
+
imageBasePath,
|
|
1308
|
+
deployedPath: typeof options.deployedPath === "string" ? URI.file(options.deployedPath) : options.deployedPath || resolveDefaultDeployedPath(),
|
|
1309
|
+
cachePath,
|
|
1310
|
+
sdkPath: typeof options.sdkPath === "string" ? URI.file(options.sdkPath) : options.sdkPath || resolveDefaultSdkPath(),
|
|
1311
|
+
configPath: typeof options.configPath === "string" ? URI.file(options.configPath) : options.configPath || resolveDefaultConfigPath(),
|
|
1312
|
+
logPath: typeof options.logPath === "string" ? URI.file(options.logPath) : options.logPath || resolveDefaultLogPath(),
|
|
1313
|
+
emulatorPath: typeof options.emulatorPath === "string" ? URI.file(options.emulatorPath) : options.emulatorPath || resolveDefaultEmulatorPath(),
|
|
1314
|
+
adapter
|
|
1144
1315
|
};
|
|
1145
1316
|
}
|
|
1146
|
-
|
|
1317
|
+
_OptionsResolver.resolveImageManagerOptions = resolveImageManagerOptions;
|
|
1318
|
+
})(OptionsResolver || (OptionsResolver = {}));
|
|
1147
1319
|
|
|
1148
1320
|
//#endregion
|
|
1149
|
-
//#region src/
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
return
|
|
1321
|
+
//#region src/sdk-list.ts
|
|
1322
|
+
let SDKList;
|
|
1323
|
+
(function(_SDKList) {
|
|
1324
|
+
function isOKResponse(result) {
|
|
1325
|
+
return "data" in result && Array.isArray(result.data);
|
|
1326
|
+
}
|
|
1327
|
+
_SDKList.isOKResponse = isOKResponse;
|
|
1328
|
+
class SDKListError extends Error {
|
|
1329
|
+
constructor(code, message, cause) {
|
|
1330
|
+
super(message);
|
|
1331
|
+
this.code = code;
|
|
1332
|
+
this.message = message;
|
|
1333
|
+
this.cause = cause;
|
|
1334
|
+
}
|
|
1154
1335
|
}
|
|
1155
|
-
|
|
1336
|
+
_SDKList.SDKListError = SDKListError;
|
|
1337
|
+
(function(_SDKListError) {
|
|
1338
|
+
_SDKListError.Code = /* @__PURE__ */ function(Code) {
|
|
1339
|
+
Code[Code["VALIDATION_ERROR"] = 400] = "VALIDATION_ERROR";
|
|
1340
|
+
Code[Code["REQUEST_ERROR"] = 500] = "REQUEST_ERROR";
|
|
1341
|
+
return Code;
|
|
1342
|
+
}({});
|
|
1343
|
+
})(SDKListError || (SDKListError = _SDKList.SDKListError || (_SDKList.SDKListError = {})));
|
|
1344
|
+
})(SDKList || (SDKList = {}));
|
|
1156
1345
|
|
|
1157
1346
|
//#endregion
|
|
1158
|
-
//#region src/
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
case "
|
|
1166
|
-
case "
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
default: return path.resolve(os.homedir(), ".huawei", "Emulator", "deployed");
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
function resolveDefaultSdkPath() {
|
|
1177
|
-
switch (process.platform) {
|
|
1178
|
-
case "darwin": return "/Applications/DevEco-Studio.app/Contents/sdk/default/openharmony";
|
|
1179
|
-
case "win32": return "C:\\Program Files\\Huawei\\DevEco Studio\\sdk\\default\\openharmony";
|
|
1180
|
-
default: return path.resolve(os.homedir(), ".huawei", "Sdk", "default", "openharmony");
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
function resolveDefaultConfigPath() {
|
|
1184
|
-
switch (process.platform) {
|
|
1185
|
-
case "darwin": return path.resolve(os.homedir(), "Library", "Application Support", "Huawei", "DevEcoStudio6.0");
|
|
1186
|
-
case "win32": return path.resolve(process.env.APPDATA ?? os.homedir(), "Roaming", "Huawei", "DevEcoStudio6.0");
|
|
1187
|
-
default: return path.resolve(os.homedir(), ".huawei", "DevEcoStudio6.0");
|
|
1347
|
+
//#region src/utils/devicetype-converter.ts
|
|
1348
|
+
let DeviceTypeConverter;
|
|
1349
|
+
(function(_DeviceTypeConverter) {
|
|
1350
|
+
function snakecaseToCamelcase(snakecaseDeviceType) {
|
|
1351
|
+
switch (snakecaseDeviceType) {
|
|
1352
|
+
case "phone": return "Phone";
|
|
1353
|
+
case "2in1": return "2in1";
|
|
1354
|
+
case "2in1_foldable": return "2in1 Foldable";
|
|
1355
|
+
case "foldable": return "Foldable";
|
|
1356
|
+
case "tablet": return "Tablet";
|
|
1357
|
+
case "triplefold": return "TripleFold";
|
|
1358
|
+
case "tv": return "TV";
|
|
1359
|
+
case "wearable": return "Wearable";
|
|
1360
|
+
case "widefold": return "WideFold";
|
|
1361
|
+
default: return snakecaseDeviceType.toLowerCase().split("_").join(" ");
|
|
1188
1362
|
}
|
|
1189
1363
|
}
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
case "darwin": return path.resolve(os.homedir(), "Library", "Logs", "Huawei", "DevEcoStudio6.0");
|
|
1193
|
-
case "win32": return path.resolve(process.env.APPDATA ?? os.homedir(), "Local", "Huawei", "DevEcoStudio6.0", "log");
|
|
1194
|
-
default: return path.resolve(os.homedir(), ".huawei", "DevEcoStudio6.0", "log");
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
function resolveDefaultEmulatorPath() {
|
|
1198
|
-
switch (process.platform) {
|
|
1199
|
-
case "darwin": return "/Applications/DevEco-Studio.app/Contents/tools/emulator";
|
|
1200
|
-
case "win32": return "C:\\Program Files\\Huawei\\DevEco Studio\\tools\\emulator";
|
|
1201
|
-
default: return path.resolve(os.homedir(), ".huawei", "Emulator");
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
const imageBasePath = options.imageBasePath || resolveDefaultImageBasePath();
|
|
1205
|
-
const cachePath = options.cachePath || path.resolve(imageBasePath, "cache");
|
|
1206
|
-
return {
|
|
1207
|
-
imageBasePath,
|
|
1208
|
-
deployedPath: options.deployedPath || resolveDefaultDeployedPath(),
|
|
1209
|
-
cachePath,
|
|
1210
|
-
sdkPath: options.sdkPath || resolveDefaultSdkPath(),
|
|
1211
|
-
configPath: options.configPath || resolveDefaultConfigPath(),
|
|
1212
|
-
logPath: options.logPath || resolveDefaultLogPath(),
|
|
1213
|
-
emulatorPath: options.emulatorPath || resolveDefaultEmulatorPath(),
|
|
1214
|
-
path,
|
|
1215
|
-
os,
|
|
1216
|
-
fs: options.fs ?? await import("node:fs"),
|
|
1217
|
-
process: options.process ?? await import("node:process"),
|
|
1218
|
-
crypto: options.crypto ?? await import("node:crypto"),
|
|
1219
|
-
child_process: options.child_process ?? await import("node:child_process")
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1364
|
+
_DeviceTypeConverter.snakecaseToCamelcase = snakecaseToCamelcase;
|
|
1365
|
+
})(DeviceTypeConverter || (DeviceTypeConverter = {}));
|
|
1222
1366
|
|
|
1223
1367
|
//#endregion
|
|
1224
1368
|
//#region src/image-manager.ts
|
|
1225
1369
|
var ImageManagerImpl = class {
|
|
1226
|
-
constructor(
|
|
1227
|
-
this.
|
|
1370
|
+
constructor(options) {
|
|
1371
|
+
this.options = options;
|
|
1228
1372
|
}
|
|
1229
1373
|
getOptions() {
|
|
1230
|
-
return this.
|
|
1374
|
+
return this.options;
|
|
1231
1375
|
}
|
|
1232
|
-
|
|
1233
|
-
switch (this.
|
|
1376
|
+
getOperatingSystem() {
|
|
1377
|
+
switch (this.options.adapter.process.platform) {
|
|
1234
1378
|
case "win32": return "windows";
|
|
1235
1379
|
case "darwin": return "mac";
|
|
1236
1380
|
default: return "linux";
|
|
1237
1381
|
}
|
|
1238
1382
|
}
|
|
1239
1383
|
getArch() {
|
|
1240
|
-
if (this.
|
|
1384
|
+
if (this.options.adapter.process.arch.toLowerCase().includes("arm")) return "arm64";
|
|
1241
1385
|
return "x86";
|
|
1242
1386
|
}
|
|
1243
|
-
async
|
|
1244
|
-
const
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1387
|
+
async requestSdkList(supportVersion = "6.0-hos-single-9") {
|
|
1388
|
+
const { adapter: { axios } } = this.getOptions();
|
|
1389
|
+
try {
|
|
1390
|
+
return await axios.post("https://devecostudio-drcn.deveco.dbankcloud.com/sdkmanager/v8/hos/getSdkList", {
|
|
1391
|
+
osArch: this.getArch(),
|
|
1392
|
+
osType: this.getOperatingSystem(),
|
|
1393
|
+
supportVersion
|
|
1394
|
+
});
|
|
1395
|
+
} catch (error) {
|
|
1396
|
+
return error;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
async safeReadAndParseSdkPkgFile(sdkPkgFileUri) {
|
|
1400
|
+
const { adapter: { fs } } = this.getOptions();
|
|
1401
|
+
try {
|
|
1402
|
+
const sdkPkgFileContent = await fs.readFile(sdkPkgFileUri).then((buffer) => buffer.toString());
|
|
1403
|
+
if (!sdkPkgFileContent.length) return void 0;
|
|
1404
|
+
return JSON.parse(sdkPkgFileContent);
|
|
1405
|
+
} catch {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
async safeReadAndParseInfoFile(infoFileUri) {
|
|
1410
|
+
const { adapter: { fs } } = this.getOptions();
|
|
1411
|
+
try {
|
|
1412
|
+
const infoFileContent = await fs.readFile(infoFileUri).then((buffer) => buffer.toString());
|
|
1413
|
+
if (!infoFileContent.length) return void 0;
|
|
1414
|
+
return JSON.parse(infoFileContent);
|
|
1415
|
+
} catch {
|
|
1416
|
+
return;
|
|
1255
1417
|
}
|
|
1256
|
-
return images;
|
|
1257
1418
|
}
|
|
1258
|
-
async
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
|
|
1419
|
+
async getLocalImages() {
|
|
1420
|
+
const { adapter: { fs, join } } = this.getOptions();
|
|
1421
|
+
const localImages = [];
|
|
1422
|
+
const systemImagePath = join(this.options.imageBasePath, "system-image");
|
|
1423
|
+
const sdkPkgFiles = await fs.glob(new RelativePattern(systemImagePath, "**/sdk-pkg.json"), { deep: 3 });
|
|
1424
|
+
for (const sdkPkgFileUri of sdkPkgFiles) {
|
|
1425
|
+
const sdkPkgFile = await this.safeReadAndParseSdkPkgFile(sdkPkgFileUri);
|
|
1426
|
+
if (!sdkPkgFile) continue;
|
|
1427
|
+
const infoFile = await this.safeReadAndParseInfoFile(sdkPkgFileUri.with({ path: sdkPkgFileUri.path.replace("sdk-pkg.json", "info.json") }));
|
|
1428
|
+
if (!infoFile) continue;
|
|
1429
|
+
localImages.push(new LocalImageImpl(this, sdkPkgFile, infoFile));
|
|
1430
|
+
}
|
|
1431
|
+
return localImages;
|
|
1432
|
+
}
|
|
1433
|
+
async getRemoteImages(supportVersion = "6.0-hos-single-9") {
|
|
1434
|
+
const remoteImages = [];
|
|
1435
|
+
const { adapter: { isAxiosError } } = this.getOptions();
|
|
1436
|
+
const resultOrError = await this.requestSdkList(supportVersion);
|
|
1437
|
+
if (isAxiosError(resultOrError)) return new SDKList.SDKListError(SDKList.SDKListError.Code.REQUEST_ERROR, "Request failed with image sdk list.", resultOrError);
|
|
1438
|
+
if (!Array.isArray(resultOrError.data)) return new SDKList.SDKListError(SDKList.SDKListError.Code.REQUEST_ERROR, "Request failed with image sdk list.", resultOrError);
|
|
1439
|
+
for (const item of resultOrError.data) {
|
|
1440
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) continue;
|
|
1441
|
+
remoteImages.push(new RemoteImageImpl(this, item));
|
|
1442
|
+
}
|
|
1443
|
+
return remoteImages;
|
|
1444
|
+
}
|
|
1445
|
+
async getDownloadedRemoteImages(supportVersion) {
|
|
1446
|
+
const remoteImages = await this.getRemoteImages(supportVersion);
|
|
1447
|
+
if (remoteImages instanceof SDKList.SDKListError) return remoteImages;
|
|
1448
|
+
const downloadedRemoteImages = [];
|
|
1449
|
+
for (const remoteImage of remoteImages) {
|
|
1450
|
+
if (!await remoteImage.getLocalImage()) continue;
|
|
1451
|
+
downloadedRemoteImages.push(remoteImage);
|
|
1452
|
+
}
|
|
1453
|
+
return downloadedRemoteImages;
|
|
1262
1454
|
}
|
|
1263
|
-
|
|
1264
|
-
const
|
|
1265
|
-
|
|
1266
|
-
|
|
1455
|
+
getListsFilePath() {
|
|
1456
|
+
const { deployedPath, adapter: { join } } = this.getOptions();
|
|
1457
|
+
return join(deployedPath, "lists.json");
|
|
1458
|
+
}
|
|
1459
|
+
async readListsFile() {
|
|
1460
|
+
try {
|
|
1461
|
+
const { adapter: { fs } } = this.getOptions();
|
|
1462
|
+
const listsFilePath = this.getListsFilePath();
|
|
1463
|
+
const listsFileContent = await fs.readFile(listsFilePath).then((buffer) => buffer.toString());
|
|
1464
|
+
if (!listsFileContent.length) return new ListsFileImpl(this, []);
|
|
1465
|
+
return new ListsFileImpl(this, JSON.parse(listsFileContent));
|
|
1466
|
+
} catch {
|
|
1467
|
+
return new ListsFileImpl(this, []);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
async readEmulatorFile() {
|
|
1471
|
+
try {
|
|
1472
|
+
const { adapter: { fs, join } } = this.getOptions();
|
|
1473
|
+
const emulatorFilePath = join(this.options.emulatorPath, "emulator.json");
|
|
1474
|
+
const emulatorFileContent = await fs.readFile(emulatorFilePath).then((buffer) => buffer.toString());
|
|
1475
|
+
if (!emulatorFileContent.length) return new EmulatorFileImpl(this, (await import("./default-emulator-config.mjs")).default);
|
|
1476
|
+
return new EmulatorFileImpl(this, JSON.parse(emulatorFileContent));
|
|
1477
|
+
} catch {
|
|
1478
|
+
return new EmulatorFileImpl(this, (await import("./default-emulator-config.mjs")).default);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
async readProductConfigFile() {
|
|
1482
|
+
try {
|
|
1483
|
+
const { adapter: { fs, join } } = this.getOptions();
|
|
1484
|
+
const productConfigFilePath = join(this.options.emulatorPath, "product-config.json");
|
|
1485
|
+
const productConfigFileContent = await fs.readFile(productConfigFilePath).then((buffer) => buffer.toString());
|
|
1486
|
+
if (!productConfigFileContent.length) return new ProductConfigFileImpl(this, (await import("./default-product-config.mjs")).default);
|
|
1487
|
+
return new ProductConfigFileImpl(this, JSON.parse(productConfigFileContent));
|
|
1488
|
+
} catch {
|
|
1489
|
+
return new ProductConfigFileImpl(this, (await import("./default-product-config.mjs")).default);
|
|
1490
|
+
}
|
|
1267
1491
|
}
|
|
1268
|
-
async
|
|
1269
|
-
const
|
|
1270
|
-
|
|
1271
|
-
|
|
1492
|
+
async getDeployedDevices() {
|
|
1493
|
+
const deployedDevices = [];
|
|
1494
|
+
const listsFile = await this.readListsFile();
|
|
1495
|
+
const productConfigFile = await this.readProductConfigFile();
|
|
1496
|
+
const emulatorFile = await this.readEmulatorFile();
|
|
1497
|
+
for (const listFileItem of listsFile.getListsFileItems()) {
|
|
1498
|
+
const productConfigItem = productConfigFile.findProductConfigItem({
|
|
1499
|
+
deviceType: DeviceTypeConverter.snakecaseToCamelcase(listFileItem.getContent().type),
|
|
1500
|
+
name: listFileItem.getContent().model
|
|
1501
|
+
});
|
|
1502
|
+
if (!productConfigItem) continue;
|
|
1503
|
+
const emulatorDeviceItem = emulatorFile.findDeviceItem({
|
|
1504
|
+
deviceType: listFileItem.getContent().type,
|
|
1505
|
+
apiVersion: Number(listFileItem.getContent().apiVersion)
|
|
1506
|
+
});
|
|
1507
|
+
if (!emulatorDeviceItem) continue;
|
|
1508
|
+
const screen = new ScreenPresetImpl({
|
|
1509
|
+
productConfigItem,
|
|
1510
|
+
emulatorDeviceItem
|
|
1511
|
+
});
|
|
1512
|
+
const device = new DeviceImpl({
|
|
1513
|
+
imageManager: this,
|
|
1514
|
+
listsFile,
|
|
1515
|
+
listFileItem,
|
|
1516
|
+
screen
|
|
1517
|
+
});
|
|
1518
|
+
const configIniFileUri = ConfigIniFileImpl.getFileUri(device);
|
|
1519
|
+
const parsedConfigIniFile = await ConfigIniFileImpl.safeReadAndParse(device);
|
|
1520
|
+
if (!parsedConfigIniFile) {
|
|
1521
|
+
listsFile.deleteListsFileItem(listFileItem);
|
|
1522
|
+
continue;
|
|
1523
|
+
}
|
|
1524
|
+
device.setConfigIniFile(new ConfigIniFileImpl(device, configIniFileUri, parsedConfigIniFile));
|
|
1525
|
+
const namedIniFileUri = NamedIniFileImpl.getFileUri(device);
|
|
1526
|
+
const parsedNamedIniFile = await NamedIniFileImpl.safeReadAndParse(device);
|
|
1527
|
+
if (!parsedNamedIniFile) {
|
|
1528
|
+
listsFile.deleteListsFileItem(listFileItem);
|
|
1529
|
+
continue;
|
|
1530
|
+
}
|
|
1531
|
+
device.setNamedIniFile(new NamedIniFileImpl(device, namedIniFileUri, parsedNamedIniFile));
|
|
1532
|
+
deployedDevices.push(device);
|
|
1533
|
+
}
|
|
1534
|
+
if (listsFile.isChanged) listsFile.write();
|
|
1535
|
+
return deployedDevices;
|
|
1536
|
+
}
|
|
1537
|
+
toJSON() {
|
|
1538
|
+
return {
|
|
1539
|
+
options: this.getOptions(),
|
|
1540
|
+
operatingSystem: this.getOperatingSystem(),
|
|
1541
|
+
arch: this.getArch(),
|
|
1542
|
+
listsFilePath: this.getListsFilePath()
|
|
1543
|
+
};
|
|
1272
1544
|
}
|
|
1273
1545
|
async isCompatible() {
|
|
1274
|
-
const { fs,
|
|
1275
|
-
const sdkPkgPath =
|
|
1276
|
-
if (!fs.
|
|
1277
|
-
const sdkPkg = JSON.parse(fs.
|
|
1546
|
+
const { emulatorPath, adapter: { fs, join, URI } } = this.getOptions();
|
|
1547
|
+
const sdkPkgPath = join(emulatorPath, "sdk-pkg.json").fsPath;
|
|
1548
|
+
if (!await fs.isFile(URI.file(sdkPkgPath))) return false;
|
|
1549
|
+
const sdkPkg = JSON.parse(await fs.readFile(URI.file(sdkPkgPath)).then((buffer) => buffer.toString()));
|
|
1278
1550
|
if (!sdkPkg?.data?.version || typeof sdkPkg.data.version !== "string") return false;
|
|
1279
1551
|
const [major, minor, patch] = sdkPkg.data.version.split(".").map(Number);
|
|
1552
|
+
const satisfies = (await import("semver/functions/satisfies")).default;
|
|
1280
1553
|
return satisfies(`${major}.${minor}.${patch}`, ">=6.0.2");
|
|
1281
1554
|
}
|
|
1282
1555
|
};
|
|
1283
|
-
async function createImageManager(options
|
|
1284
|
-
return new ImageManagerImpl(await resolveImageManagerOptions(options));
|
|
1556
|
+
async function createImageManager(options) {
|
|
1557
|
+
return new ImageManagerImpl(await OptionsResolver.resolveImageManagerOptions(options));
|
|
1285
1558
|
}
|
|
1286
1559
|
|
|
1287
1560
|
//#endregion
|
|
1288
|
-
export {
|
|
1561
|
+
export { BaseImage, ConfigIniFile, CustomizeFoldableScreen, CustomizeScreen, Device, EmulatorBasicItem, EmulatorFile, EmulatorFoldItem, EmulatorGroupItem, EmulatorTripleFoldItem, ListsFile, ListsFileItem, LocalImage, ProductConfigFile, ProductConfigItem, RemoteImage, SDKList, ScreenPreset, createImageManager, version };
|