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