@arkts/image-manager 0.4.3 → 0.5.1

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