@arkts/image-manager 0.4.2 → 0.5.0

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