@oniroproject/core 0.7.0 → 0.8.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
@@ -37,22 +37,28 @@ __export(index_exports, {
37
37
  ChecksumMismatchError: () => ChecksumMismatchError,
38
38
  CmdToolsNotInstalledError: () => CmdToolsNotInstalledError,
39
39
  CommandFailedError: () => CommandFailedError,
40
+ INSTALL_TMP_DIRNAME: () => INSTALL_TMP_DIRNAME,
41
+ InsufficientSpaceError: () => InsufficientSpaceError,
40
42
  OHOS_URL_BASE: () => OHOS_URL_BASE,
41
43
  OniroError: () => OniroError,
42
44
  SdkNotInstalledError: () => SdkNotInstalledError,
45
+ TMP_DIR_HINT: () => TMP_DIR_HINT,
43
46
  UnsupportedPlatformError: () => UnsupportedPlatformError,
44
47
  VERSION: () => VERSION,
45
48
  applyChanges: () => applyChanges,
46
49
  attemptHdcConnection: () => attemptHdcConnection,
47
50
  buildGestureCommands: () => buildGestureCommands,
51
+ buildGestureUitestCommand: () => buildGestureUitestCommand,
48
52
  buildHap: () => buildHap,
49
53
  buildHvigorwArgs: () => buildHvigorwArgs,
50
54
  buildInputCommand: () => buildInputCommand,
51
55
  buildRawTouchCommand: () => buildRawTouchCommand,
52
56
  captureBurst: () => captureBurst,
53
57
  consoleLogger: () => consoleLogger,
58
+ createInstallTempDir: () => createInstallTempDir,
54
59
  createMaterial: () => createMaterial,
55
60
  createScaffold: () => createScaffold,
61
+ createTempWorkDir: () => createTempWorkDir,
56
62
  decideInstallMethod: () => decideInstallMethod,
57
63
  decideReboot: () => decideReboot,
58
64
  decryptPwd: () => decryptPwd,
@@ -73,14 +79,17 @@ __export(index_exports, {
73
79
  dumpScreen: () => dumpScreen,
74
80
  dumpWindow: () => dumpWindow,
75
81
  encryptPwd: () => encryptPwd,
82
+ ensureFreeSpace: () => ensureFreeSpace,
76
83
  ensureOhModules: () => ensureOhModules,
77
84
  ensureOk: () => ensureOk,
85
+ ensureRemoteOk: () => ensureRemoteOk,
78
86
  extractTarball: () => extractTarball,
79
87
  extractZipWithProgress: () => extractZipWithProgress,
80
88
  findAppProcessId: () => findAppProcessId,
81
89
  findCmdToolsSourceDir: () => findCmdToolsSourceDir,
82
90
  findRunningProcess: () => findRunningProcess,
83
91
  forceStop: () => forceStop,
92
+ formatBytes: () => formatBytes,
84
93
  generateSigningConfigs: () => generateSigningConfigs,
85
94
  getBundleName: () => getBundleName,
86
95
  getCmdToolsBin: () => getCmdToolsBin,
@@ -90,6 +99,7 @@ __export(index_exports, {
90
99
  getDeviceInfo: () => getDeviceInfo,
91
100
  getDisplaySize: () => getDisplaySize,
92
101
  getEmulatorDir: () => getEmulatorDir,
102
+ getFreeSpaceBytes: () => getFreeSpaceBytes,
93
103
  getHdcPath: () => getHdcPath,
94
104
  getHvigorwPath: () => getHvigorwPath,
95
105
  getInstalledSdks: () => getInstalledSdks,
@@ -107,6 +117,8 @@ __export(index_exports, {
107
117
  installEmulator: () => installEmulator,
108
118
  isCmdToolsInstalled: () => isCmdToolsInstalled,
109
119
  isEmulatorInstalled: () => isEmulatorInstalled,
120
+ isOutOfSpaceError: () => isOutOfSpaceError,
121
+ isRamBackedPath: () => isRamBackedPath,
110
122
  isValidBundleName: () => isValidBundleName,
111
123
  isValidProjectName: () => isValidProjectName,
112
124
  launchApp: () => launchApp,
@@ -124,6 +136,8 @@ __export(index_exports, {
124
136
  parseCodelinterFindings: () => parseCodelinterFindings,
125
137
  parseDeviceList: () => parseDeviceList,
126
138
  parseHilogLine: () => parseHilogLine,
139
+ parseMainAbilityFromBmDump: () => parseMainAbilityFromBmDump,
140
+ parseRemoteExit: () => parseRemoteExit,
127
141
  pickSigningKind: () => pickSigningKind,
128
142
  prepareSigning: () => prepareSigning,
129
143
  pruneLayout: () => pruneLayout,
@@ -134,6 +148,8 @@ __export(index_exports, {
134
148
  removeCmdTools: () => removeCmdTools,
135
149
  removeEmulator: () => removeEmulator,
136
150
  removeSdk: () => removeSdk,
151
+ removeTempWorkDir: () => removeTempWorkDir,
152
+ resolveTmpRoot: () => resolveTmpRoot,
137
153
  runCodelinter: () => runCodelinter,
138
154
  runHvigorw: () => runHvigorw,
139
155
  runOhpm: () => runOhpm,
@@ -146,11 +162,13 @@ __export(index_exports, {
146
162
  sendRawTouch: () => sendRawTouch,
147
163
  setHilogLevel: () => setHilogLevel,
148
164
  shell: () => shell,
165
+ shellChecked: () => shellChecked,
149
166
  startEmulator: () => startEmulator,
150
167
  staticConfig: () => staticConfig,
151
168
  stopEmulator: () => stopEmulator,
152
169
  streamHilog: () => streamHilog,
153
170
  takeScreenshot: () => takeScreenshot,
171
+ toSpaceError: () => toSpaceError,
154
172
  uninstallApp: () => uninstallApp,
155
173
  validateTemplateLayout: () => validateTemplateLayout,
156
174
  verifySha256: () => verifySha256,
@@ -159,6 +177,7 @@ __export(index_exports, {
159
177
  waitForCondition: () => waitForCondition,
160
178
  waitForLog: () => waitForLog,
161
179
  watchLog: () => watchLog,
180
+ waypointsToRawEvents: () => waypointsToRawEvents,
162
181
  writeJson5File: () => writeJson5File,
163
182
  writeJsonFile: () => writeJsonFile
164
183
  });
@@ -271,9 +290,9 @@ var CmdToolsNotInstalledError = class extends OniroError {
271
290
  expectedPath;
272
291
  };
273
292
  var UnsupportedPlatformError = class extends OniroError {
274
- constructor(platform6) {
275
- super(`Unsupported platform: ${platform6}.`);
276
- this.platform = platform6;
293
+ constructor(platform7) {
294
+ super(`Unsupported platform: ${platform7}.`);
295
+ this.platform = platform7;
277
296
  this.name = "UnsupportedPlatformError";
278
297
  }
279
298
  platform;
@@ -288,6 +307,14 @@ var ChecksumMismatchError = class extends OniroError {
288
307
  expected;
289
308
  actual;
290
309
  };
310
+ var InsufficientSpaceError = class extends OniroError {
311
+ constructor(message, dir, cause) {
312
+ super(message, cause);
313
+ this.dir = dir;
314
+ this.name = "InsufficientSpaceError";
315
+ }
316
+ dir;
317
+ };
291
318
  var CancelledError = class extends OniroError {
292
319
  constructor(message = "Operation cancelled.") {
293
320
  super(message);
@@ -334,29 +361,29 @@ var OHOS_URL_BASE = "https://repo.huaweicloud.com/openharmony/os";
334
361
  // src/sdk/platform.ts
335
362
  var os2 = __toESM(require("os"), 1);
336
363
  function getOsFolder() {
337
- const platform6 = os2.platform();
338
- if (platform6 === "linux") return "linux";
339
- if (platform6 === "darwin") return "darwin";
340
- if (platform6 === "win32") return "windows";
341
- throw new UnsupportedPlatformError(platform6);
364
+ const platform7 = os2.platform();
365
+ if (platform7 === "linux") return "linux";
366
+ if (platform7 === "darwin") return "darwin";
367
+ if (platform7 === "win32") return "windows";
368
+ throw new UnsupportedPlatformError(platform7);
342
369
  }
343
370
  function getSdkFilename(version) {
344
- const platform6 = os2.platform();
371
+ const platform7 = os2.platform();
345
372
  const v = version ?? ALL_SDKS[ALL_SDKS.length - 1].version;
346
373
  const strips = ALL_SDKS.find((r) => r.version === v)?.tarballStrip ?? { linuxWindows: 1, darwin: 3 };
347
- if (platform6 === "linux") {
374
+ if (platform7 === "linux") {
348
375
  return { filename: "ohos-sdk-windows_linux-public.tar.gz", osFolder: "linux", strip: strips.linuxWindows };
349
376
  }
350
- if (platform6 === "darwin") {
377
+ if (platform7 === "darwin") {
351
378
  if (os2.arch() === "arm64") {
352
379
  return { filename: "L2-SDK-MAC-M1-PUBLIC.tar.gz", osFolder: "darwin", strip: strips.darwin };
353
380
  }
354
381
  return { filename: "ohos-sdk-mac-public.tar.gz", osFolder: "darwin", strip: strips.darwin };
355
382
  }
356
- if (platform6 === "win32") {
383
+ if (platform7 === "win32") {
357
384
  return { filename: "ohos-sdk-windows_linux-public.tar.gz", osFolder: "windows", strip: strips.linuxWindows };
358
385
  }
359
- throw new UnsupportedPlatformError(platform6);
386
+ throw new UnsupportedPlatformError(platform7);
360
387
  }
361
388
 
362
389
  // src/sdk/paths.ts
@@ -397,6 +424,8 @@ function getOhpmPath(config) {
397
424
  return getCmdToolsBin(config, "ohpm");
398
425
  }
399
426
  function getHdcPath(config) {
427
+ const override = config.get("hdcPath", "");
428
+ if (override) return override;
400
429
  const base = path2.join(getCmdToolsPath(config), "sdk", "default", "openharmony", "toolchains");
401
430
  if (os3.platform() === "win32") {
402
431
  return pickExisting([
@@ -447,8 +476,164 @@ function detectProjectSdkVersion(projectRoot, logger = noopLogger) {
447
476
  }
448
477
  }
449
478
 
450
- // src/sdk/download.ts
479
+ // src/sdk/tmp.ts
451
480
  var fs3 = __toESM(require("fs"), 1);
481
+ var os4 = __toESM(require("os"), 1);
482
+ var path4 = __toESM(require("path"), 1);
483
+ var INSTALL_TMP_DIRNAME = ".oniro-tmp";
484
+ var TMPFS_MAGIC = 16914836;
485
+ var RAMFS_MAGIC = 2240043254;
486
+ var HINT_EXAMPLE = os4.platform() === "win32" ? "D:\\oniro-tmp" : "~/.cache/oniro-tmp";
487
+ var TMP_DIR_HINT = `Point the scratch directory at a filesystem with more room using --tmp-dir <path> (or the ONIRO_TMP_DIR environment variable), e.g. --tmp-dir ${HINT_EXAMPLE}.`;
488
+ function resolveTmpRoot(config, override, installRoot) {
489
+ const explicit = (override ?? "").trim();
490
+ if (explicit) return path4.resolve(explicit);
491
+ const configured = config.get("tmpDir", "").trim();
492
+ if (configured) return path4.resolve(configured);
493
+ if (installRoot) return path4.join(path4.resolve(installRoot), INSTALL_TMP_DIRNAME);
494
+ return os4.tmpdir();
495
+ }
496
+ function createTempWorkDir(root, prefix) {
497
+ try {
498
+ fs3.mkdirSync(root, { recursive: true });
499
+ return fs3.mkdtempSync(path4.join(root, prefix));
500
+ } catch (err) {
501
+ if (isOutOfSpaceError(err)) throw toSpaceError(err, root, "a temporary directory");
502
+ throw new OniroError(
503
+ `Cannot create a temporary directory in '${root}': ${err instanceof Error ? err.message : String(err)}
504
+ ${TMP_DIR_HINT}`,
505
+ err
506
+ );
507
+ }
508
+ }
509
+ function removeTempWorkDir(dir, root) {
510
+ fs3.rmSync(dir, { recursive: true, force: true });
511
+ if (!root || path4.basename(root) !== INSTALL_TMP_DIRNAME) return;
512
+ try {
513
+ fs3.rmdirSync(root);
514
+ } catch {
515
+ }
516
+ }
517
+ function createInstallTempDir(opts) {
518
+ const requested = (opts.override ?? "").trim() || opts.config.get("tmpDir", "").trim();
519
+ const root = resolveTmpRoot(opts.config, opts.override, opts.installRoot);
520
+ try {
521
+ return { dir: createTempWorkDir(root, opts.prefix), root };
522
+ } catch (err) {
523
+ const fallback = os4.tmpdir();
524
+ if (requested || isOutOfSpaceError(err) || path4.resolve(fallback) === path4.resolve(root)) throw err;
525
+ const reason = err instanceof Error ? err.message.split("\n")[0] : String(err);
526
+ (opts.logger ?? noopLogger).warn(`${reason} Falling back to '${fallback}'.`);
527
+ return { dir: createTempWorkDir(fallback, opts.prefix), root: fallback };
528
+ }
529
+ }
530
+ function nearestExisting(dir) {
531
+ let current = path4.resolve(dir);
532
+ for (; ; ) {
533
+ if (fs3.existsSync(current)) return current;
534
+ const parent = path4.dirname(current);
535
+ if (parent === current) return null;
536
+ current = parent;
537
+ }
538
+ }
539
+ function getFreeSpaceBytes(dir) {
540
+ const target = nearestExisting(dir);
541
+ if (!target) return null;
542
+ try {
543
+ const stats = fs3.statfsSync(target);
544
+ return Number(stats.bsize) * Number(stats.bavail);
545
+ } catch {
546
+ return null;
547
+ }
548
+ }
549
+ function isRamBackedPath(dir) {
550
+ const target = nearestExisting(dir);
551
+ if (!target) return false;
552
+ try {
553
+ const type = Number(fs3.statfsSync(target).type);
554
+ return type === TMPFS_MAGIC || type === RAMFS_MAGIC;
555
+ } catch {
556
+ return false;
557
+ }
558
+ }
559
+ function formatBytes(bytes) {
560
+ const units = ["B", "KiB", "MiB", "GiB", "TiB"];
561
+ let value = Math.max(0, bytes);
562
+ let unit = 0;
563
+ while (value >= 1024 && unit < units.length - 1) {
564
+ value /= 1024;
565
+ unit++;
566
+ }
567
+ return `${value >= 10 || unit === 0 ? Math.round(value) : value.toFixed(1)} ${units[unit]}`;
568
+ }
569
+ function isOutOfSpaceError(err) {
570
+ if (err instanceof InsufficientSpaceError) return true;
571
+ const seen = /* @__PURE__ */ new Set();
572
+ let current = err;
573
+ while (current && typeof current === "object" && !seen.has(current)) {
574
+ seen.add(current);
575
+ const e = current;
576
+ if (e.code === "ENOSPC" || e.code === "EDQUOT") return true;
577
+ if (typeof e.message === "string" && /ENOSPC|EDQUOT|no space left on device/i.test(e.message)) return true;
578
+ current = e.cause;
579
+ }
580
+ return false;
581
+ }
582
+ function spaceMessage(dir, what, opts) {
583
+ const need = typeof opts.requiredBytes === "number" ? `needs about ${formatBytes(opts.requiredBytes)}` : null;
584
+ const free = typeof opts.freeBytes === "number" ? `${formatBytes(opts.freeBytes)} available` : null;
585
+ const amounts = [need, free].filter(Boolean).join(", ");
586
+ const lines = [`Not enough free space in '${dir}' for ${what}${amounts ? ` (${amounts})` : ""}.`];
587
+ if (isRamBackedPath(dir)) {
588
+ lines.push(
589
+ `'${dir}' is on a RAM-backed filesystem (tmpfs), so its capacity is limited by free memory, not by free disk.`
590
+ );
591
+ }
592
+ if (opts.tmpDirHint) lines.push(TMP_DIR_HINT);
593
+ return lines.join("\n");
594
+ }
595
+ function ensureFreeSpace(dir, requiredBytes, what) {
596
+ if (!Number.isFinite(requiredBytes) || requiredBytes <= 0) return;
597
+ const freeBytes = getFreeSpaceBytes(dir);
598
+ if (freeBytes === null || freeBytes >= requiredBytes) return;
599
+ throw new InsufficientSpaceError(
600
+ spaceMessage(dir, what, { requiredBytes, freeBytes, tmpDirHint: true }),
601
+ dir
602
+ );
603
+ }
604
+ function errorPath(err) {
605
+ const seen = /* @__PURE__ */ new Set();
606
+ let current = err;
607
+ while (current && typeof current === "object" && !seen.has(current)) {
608
+ seen.add(current);
609
+ const e = current;
610
+ if (typeof e.path === "string" && e.path) return e.path;
611
+ if (typeof e.dest === "string" && e.dest) return e.dest;
612
+ current = e.cause;
613
+ }
614
+ return null;
615
+ }
616
+ function isInside(child, parent) {
617
+ const rel = path4.relative(path4.resolve(parent), path4.resolve(child));
618
+ return rel === "" || !rel.startsWith("..") && !path4.isAbsolute(rel);
619
+ }
620
+ function toSpaceError(err, tmpRoot, what) {
621
+ if (err instanceof InsufficientSpaceError) return err;
622
+ if (!isOutOfSpaceError(err)) return err;
623
+ const failed = errorPath(err);
624
+ const failedDir = failed ? path4.dirname(path4.resolve(failed)) : path4.resolve(tmpRoot);
625
+ const inTmp = isInside(failedDir, tmpRoot);
626
+ const dir = inTmp ? path4.resolve(tmpRoot) : failedDir;
627
+ return new InsufficientSpaceError(
628
+ spaceMessage(dir, what, { freeBytes: getFreeSpaceBytes(dir), tmpDirHint: inTmp }),
629
+ dir,
630
+ err
631
+ );
632
+ }
633
+
634
+ // src/sdk/download.ts
635
+ var fs4 = __toESM(require("fs"), 1);
636
+ var path5 = __toESM(require("path"), 1);
452
637
  var crypto = __toESM(require("crypto"), 1);
453
638
  var import_node_stream = require("stream");
454
639
  var import_node_util = require("util");
@@ -458,36 +643,57 @@ var pipelineAsync = (0, import_node_util.promisify)(import_node_stream.pipeline)
458
643
  async function downloadFile(opts) {
459
644
  const { url, dest, progress, abortSignal } = opts;
460
645
  const proto = url.startsWith("https") ? https : http;
461
- return new Promise((resolve2, reject) => {
646
+ return new Promise((resolve4, reject) => {
462
647
  const s = Math.max(0, Math.min(100, opts.start ?? 0));
463
648
  const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));
464
649
  let settled = false;
465
650
  const done = (err) => {
466
651
  if (settled) return;
467
652
  settled = true;
468
- err ? reject(err) : resolve2();
653
+ err ? reject(err) : resolve4();
469
654
  };
470
655
  if (abortSignal?.aborted) {
471
656
  done(new CancelledError("Download cancelled before start."));
472
657
  return;
473
658
  }
474
- const file = fs3.createWriteStream(dest);
659
+ const destDir = path5.dirname(path5.resolve(dest));
660
+ const what = opts.what ?? `the download of '${url}'`;
661
+ const writeFailed = (err) => isOutOfSpaceError(err) ? toSpaceError(err, opts.tmpRoot ?? destDir, what) : new OniroError(`Error writing '${dest}': ${err instanceof Error ? err.message : String(err)}`, err);
662
+ const file = fs4.createWriteStream(dest);
663
+ let activeResponse;
664
+ const failWith = (err) => {
665
+ file.close(() => fs4.rm(dest, { force: true }, () => done(err)));
666
+ };
667
+ file.on("error", (err) => {
668
+ try {
669
+ activeResponse?.destroy?.();
670
+ } catch {
671
+ }
672
+ failWith(writeFailed(err));
673
+ });
475
674
  const req = proto.get(url, (response) => {
675
+ activeResponse = response;
476
676
  if (response.statusCode !== 200) {
477
677
  try {
478
678
  response.destroy();
479
679
  } catch {
480
680
  }
481
- try {
482
- file.close();
483
- } catch {
484
- }
485
- fs3.unlink(dest, () => {
486
- });
487
- done(new OniroError(`Failed to download '${url}' (HTTP ${response.statusCode})`));
681
+ failWith(new OniroError(`Failed to download '${url}' (HTTP ${response.statusCode})`));
488
682
  return;
489
683
  }
490
684
  const total = parseInt(response.headers["content-length"] || "0", 10);
685
+ if (total > 0) {
686
+ try {
687
+ ensureFreeSpace(opts.tmpRoot ?? destDir, total, what);
688
+ } catch (err) {
689
+ try {
690
+ response.destroy();
691
+ } catch {
692
+ }
693
+ failWith(err);
694
+ return;
695
+ }
696
+ }
491
697
  let downloaded = 0;
492
698
  let lastOverall = Math.round(s);
493
699
  response.on("data", (chunk) => {
@@ -511,38 +717,26 @@ async function downloadFile(opts) {
511
717
  const inc = endOverall - lastOverall;
512
718
  if (inc > 0) progress.report({ message: "Downloading: 100%", increment: inc });
513
719
  }
514
- file.close((err) => err ? done(err) : done());
720
+ file.close((err) => err ? done(writeFailed(err)) : done());
515
721
  });
516
722
  abortSignal?.addEventListener("abort", () => {
517
723
  response.destroy();
518
- file.close();
519
- fs3.unlink(dest, () => {
520
- });
521
- done(new CancelledError("Download cancelled."));
724
+ failWith(new CancelledError("Download cancelled."));
522
725
  });
523
726
  });
524
727
  req.on("error", (err) => {
525
- try {
526
- file.close();
527
- } catch {
528
- }
529
- fs3.unlink(dest, () => {
530
- });
531
- done(new OniroError(`Error downloading '${url}': ${err.message}`, err));
728
+ failWith(new OniroError(`Error downloading '${url}': ${err.message}`, err));
532
729
  });
533
730
  abortSignal?.addEventListener("abort", () => {
534
731
  req.destroy();
535
- file.close();
536
- fs3.unlink(dest, () => {
537
- });
538
- done(new CancelledError("Download cancelled."));
732
+ failWith(new CancelledError("Download cancelled."));
539
733
  });
540
734
  });
541
735
  }
542
736
  async function verifySha256(filePath, sha256Path) {
543
- const expected = fs3.readFileSync(sha256Path, "utf8").split(/\s+/)[0];
737
+ const expected = fs4.readFileSync(sha256Path, "utf8").split(/\s+/)[0];
544
738
  const hash = crypto.createHash("sha256");
545
- await pipelineAsync(fs3.createReadStream(filePath), hash);
739
+ await pipelineAsync(fs4.createReadStream(filePath), hash);
546
740
  const actual = hash.digest("hex");
547
741
  if (actual !== expected) {
548
742
  throw new ChecksumMismatchError(expected, actual);
@@ -550,9 +744,9 @@ async function verifySha256(filePath, sha256Path) {
550
744
  }
551
745
 
552
746
  // src/sdk/extract.ts
553
- var fs4 = __toESM(require("fs"), 1);
554
- var os4 = __toESM(require("os"), 1);
555
- var path4 = __toESM(require("path"), 1);
747
+ var fs5 = __toESM(require("fs"), 1);
748
+ var os5 = __toESM(require("os"), 1);
749
+ var path6 = __toESM(require("path"), 1);
556
750
  var import_node_stream2 = require("stream");
557
751
  var import_node_util2 = require("util");
558
752
  var tar = __toESM(require("tar"), 1);
@@ -569,12 +763,12 @@ async function extractZipWithProgress(opts) {
569
763
  const r = Math.max(0, Math.min(100 - s, opts.range ?? 100));
570
764
  let processed = 0;
571
765
  let lastOverall = Math.round(s);
572
- await fs4.promises.mkdir(dest, { recursive: true });
573
- const destRoot = path4.resolve(dest);
766
+ await fs5.promises.mkdir(dest, { recursive: true });
767
+ const destRoot = path6.resolve(dest);
574
768
  const safeResolveTarget = (entryName) => {
575
- const resolved = path4.resolve(destRoot, entryName);
576
- const rel = path4.relative(destRoot, resolved);
577
- if (rel.startsWith("..") || path4.isAbsolute(rel)) {
769
+ const resolved = path6.resolve(destRoot, entryName);
770
+ const rel = path6.relative(destRoot, resolved);
771
+ if (rel.startsWith("..") || path6.isAbsolute(rel)) {
578
772
  throw new OniroError(`Blocked ZIP entry with illegal path: ${entryName}`);
579
773
  }
580
774
  return resolved;
@@ -586,25 +780,25 @@ async function extractZipWithProgress(opts) {
586
780
  const attr = file.attr ? file.attr >>> 16 : 0;
587
781
  const isSymlink = "isSymbolicLink" in file ? Boolean(file.isSymbolicLink) : (attr & 61440) === 40960;
588
782
  if (file.isDirectory) {
589
- await fs4.promises.mkdir(targetPath, { recursive: true });
783
+ await fs5.promises.mkdir(targetPath, { recursive: true });
590
784
  } else if (isSymlink) {
591
- await fs4.promises.mkdir(path4.dirname(targetPath), { recursive: true });
785
+ await fs5.promises.mkdir(path6.dirname(targetPath), { recursive: true });
592
786
  const linkTargetBuffer = await zip.entryData(file);
593
787
  const linkTarget = linkTargetBuffer.toString("utf8");
594
788
  try {
595
- const isWin = os4.platform() === "win32";
596
- await fs4.promises.symlink(linkTarget, targetPath, isWin ? "file" : void 0);
789
+ const isWin = os5.platform() === "win32";
790
+ await fs5.promises.symlink(linkTarget, targetPath, isWin ? "file" : void 0);
597
791
  } catch (e) {
598
792
  logger.warn(`Failed to create symlink at ${targetPath}: ${String(e)}`);
599
793
  }
600
794
  } else {
601
- await fs4.promises.mkdir(path4.dirname(targetPath), { recursive: true });
795
+ await fs5.promises.mkdir(path6.dirname(targetPath), { recursive: true });
602
796
  const readStream = await zip.stream(file);
603
- const writeStream = fs4.createWriteStream(targetPath);
797
+ const writeStream = fs5.createWriteStream(targetPath);
604
798
  await pipelineAsync2(readStream, writeStream);
605
799
  if (attr > 0) {
606
800
  try {
607
- await fs4.promises.chmod(targetPath, attr & 511);
801
+ await fs5.promises.chmod(targetPath, attr & 511);
608
802
  } catch {
609
803
  }
610
804
  }
@@ -636,41 +830,41 @@ async function extractTarball(tarPath, dest, strip = 0) {
636
830
  }
637
831
 
638
832
  // src/sdk/list.ts
639
- var fs5 = __toESM(require("fs"), 1);
640
- var path5 = __toESM(require("path"), 1);
833
+ var fs6 = __toESM(require("fs"), 1);
834
+ var path7 = __toESM(require("path"), 1);
641
835
  function getSupportedSdksForUi(config) {
642
- const base = path5.join(getSdkRootDir(config), getOsFolder());
836
+ const base = path7.join(getSdkRootDir(config), getOsFolder());
643
837
  return ALL_SDKS.map((sdk) => ({
644
838
  version: sdk.version,
645
839
  api: sdk.api,
646
- installed: fs5.existsSync(path5.join(base, sdk.api))
840
+ installed: fs6.existsSync(path7.join(base, sdk.api))
647
841
  })).sort((a, b) => Number(b.api) - Number(a.api));
648
842
  }
649
843
  function getInstalledSdks(config) {
650
844
  const sdkRoot = getSdkRootDir(config);
651
845
  const versions = /* @__PURE__ */ new Set();
652
- if (!fs5.existsSync(sdkRoot)) return [];
846
+ if (!fs6.existsSync(sdkRoot)) return [];
653
847
  for (const osFolder of ["linux", "darwin", "windows"]) {
654
- const osPath = path5.join(sdkRoot, osFolder);
655
- if (!fs5.existsSync(osPath) || !fs5.statSync(osPath).isDirectory()) continue;
656
- for (const api of fs5.readdirSync(osPath)) {
657
- const apiPath = path5.join(osPath, api);
658
- if (fs5.statSync(apiPath).isDirectory()) versions.add(api);
848
+ const osPath = path7.join(sdkRoot, osFolder);
849
+ if (!fs6.existsSync(osPath) || !fs6.statSync(osPath).isDirectory()) continue;
850
+ for (const api of fs6.readdirSync(osPath)) {
851
+ const apiPath = path7.join(osPath, api);
852
+ if (fs6.statSync(apiPath).isDirectory()) versions.add(api);
659
853
  }
660
854
  }
661
855
  return ALL_SDKS.filter((sdk) => versions.has(sdk.api)).map((sdk) => sdk.version);
662
856
  }
663
857
 
664
858
  // src/sdk/remove.ts
665
- var fs6 = __toESM(require("fs"), 1);
666
- var path6 = __toESM(require("path"), 1);
859
+ var fs7 = __toESM(require("fs"), 1);
860
+ var path8 = __toESM(require("path"), 1);
667
861
  function removeSdk(config, api) {
668
862
  const sdkRoot = getSdkRootDir(config);
669
863
  let removed = false;
670
864
  for (const osFolder of ["linux", "darwin", "windows"]) {
671
- const sdkPath = path6.join(sdkRoot, osFolder, api);
672
- if (fs6.existsSync(sdkPath)) {
673
- fs6.rmSync(sdkPath, { recursive: true, force: true });
865
+ const sdkPath = path8.join(sdkRoot, osFolder, api);
866
+ if (fs7.existsSync(sdkPath)) {
867
+ fs7.rmSync(sdkPath, { recursive: true, force: true });
674
868
  removed = true;
675
869
  }
676
870
  }
@@ -678,19 +872,18 @@ function removeSdk(config, api) {
678
872
  }
679
873
 
680
874
  // src/sdk/install.ts
681
- var fs8 = __toESM(require("fs"), 1);
682
- var os5 = __toESM(require("os"), 1);
683
- var path7 = __toESM(require("path"), 1);
875
+ var fs9 = __toESM(require("fs"), 1);
876
+ var path9 = __toESM(require("path"), 1);
684
877
 
685
878
  // src/sdk/move.ts
686
- var fs7 = __toESM(require("fs"), 1);
879
+ var fs8 = __toESM(require("fs"), 1);
687
880
  function movePath(src, dest) {
688
881
  try {
689
- fs7.renameSync(src, dest);
882
+ fs8.renameSync(src, dest);
690
883
  } catch (err) {
691
884
  if (err.code !== "EXDEV") throw err;
692
- fs7.cpSync(src, dest, { recursive: true });
693
- fs7.rmSync(src, { recursive: true, force: true });
885
+ fs8.cpSync(src, dest, { recursive: true });
886
+ fs8.rmSync(src, { recursive: true, force: true });
694
887
  }
695
888
  }
696
889
 
@@ -702,21 +895,29 @@ async function downloadAndInstallSdk(opts) {
702
895
  const urlBase = config.get("sdkUrlBase", OHOS_URL_BASE);
703
896
  const downloadUrl = `${urlBase}/${version}-Release/${filename}`;
704
897
  const sha256Url = `${downloadUrl}.sha256`;
705
- const tmpDir = fs8.mkdtempSync(path7.join(os5.tmpdir(), "oniro-sdk-"));
706
- const tarPath = path7.join(tmpDir, filename);
707
- const sha256Path = path7.join(tmpDir, `${filename}.sha256`);
708
- const extractDir = path7.join(tmpDir, "extract");
709
- fs8.mkdirSync(extractDir);
710
- const sdkInstallDir = path7.join(getSdkRootDir(config), osFolder, api);
711
- fs8.mkdirSync(path7.dirname(sdkInstallDir), { recursive: true });
898
+ const what = `the SDK ${version} install`;
899
+ const sdkRoot = getSdkRootDir(config);
900
+ const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
901
+ config,
902
+ override: opts.tmpDir,
903
+ installRoot: sdkRoot,
904
+ prefix: "oniro-sdk-",
905
+ logger
906
+ });
907
+ const tarPath = path9.join(tmpDir, filename);
908
+ const sha256Path = path9.join(tmpDir, `${filename}.sha256`);
909
+ const extractDir = path9.join(tmpDir, "extract");
910
+ fs9.mkdirSync(extractDir);
911
+ const sdkInstallDir = path9.join(sdkRoot, osFolder, api);
912
+ fs9.mkdirSync(path9.dirname(sdkInstallDir), { recursive: true });
712
913
  const checkCancelled = () => {
713
914
  if (abortSignal?.aborted) throw new CancelledError();
714
915
  };
715
916
  try {
716
917
  progress?.report({ message: "Downloading SDK archive...", increment: 0 });
717
- await downloadFile({ url: downloadUrl, dest: tarPath, progress, abortSignal, start: 0, range: 35 });
918
+ await downloadFile({ url: downloadUrl, dest: tarPath, progress, abortSignal, start: 0, range: 35, what, tmpRoot });
718
919
  progress?.report({ message: "Downloading checksum...", increment: 0 });
719
- await downloadFile({ url: sha256Url, dest: sha256Path, progress, abortSignal, start: 35, range: 10 });
920
+ await downloadFile({ url: sha256Url, dest: sha256Path, progress, abortSignal, start: 35, range: 10, what, tmpRoot });
720
921
  progress?.report({ message: "Verifying checksum...", increment: 0 });
721
922
  await verifySha256(tarPath, sha256Path);
722
923
  progress?.report({ message: "Verifying checksum...", increment: 5 });
@@ -725,13 +926,13 @@ async function downloadAndInstallSdk(opts) {
725
926
  await extractTarball(tarPath, extractDir, strip);
726
927
  progress?.report({ message: "Extracting SDK (this may take a while)...", increment: 10 });
727
928
  checkCancelled();
728
- const osContentPath = path7.join(extractDir, osFolder);
729
- if (!fs8.existsSync(osContentPath)) {
929
+ const osContentPath = path9.join(extractDir, osFolder);
930
+ if (!fs9.existsSync(osContentPath)) {
730
931
  throw new OniroError(
731
932
  `Expected folder '${osFolder}' not found in extracted SDK. Tarball layout may have changed.`
732
933
  );
733
934
  }
734
- const zipFiles = fs8.readdirSync(osContentPath).filter((n2) => n2.endsWith(".zip"));
935
+ const zipFiles = fs9.readdirSync(osContentPath).filter((n2) => n2.endsWith(".zip"));
735
936
  const componentsStart = 60;
736
937
  const componentsBudget = 35;
737
938
  const n = zipFiles.length;
@@ -746,39 +947,40 @@ async function downloadAndInstallSdk(opts) {
746
947
  for (const zipFile of zipFiles) {
747
948
  checkCancelled();
748
949
  logger.info(`Extracting component ${zipFile}`);
749
- const zipPath = path7.join(osContentPath, zipFile);
950
+ const zipPath = path9.join(osContentPath, zipFile);
750
951
  const thisBudget = base + (rem > 0 ? 1 : 0);
751
952
  if (rem > 0) rem--;
752
953
  await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });
753
954
  cursor += thisBudget;
754
- fs8.unlinkSync(zipPath);
955
+ fs9.unlinkSync(zipPath);
755
956
  }
756
957
  progress?.report({ message: "Finalizing installation...", increment: 0 });
757
- if (fs8.existsSync(sdkInstallDir)) {
758
- fs8.rmSync(sdkInstallDir, { recursive: true, force: true });
958
+ if (fs9.existsSync(sdkInstallDir)) {
959
+ fs9.rmSync(sdkInstallDir, { recursive: true, force: true });
759
960
  }
760
961
  movePath(osContentPath, sdkInstallDir);
761
962
  progress?.report({ message: "Finalizing installation...", increment: 3 });
762
963
  progress?.report({ message: "Cleaning up...", increment: 0 });
763
- fs8.rmSync(tmpDir, { recursive: true, force: true });
964
+ removeTempWorkDir(tmpDir, tmpRoot);
764
965
  progress?.report({ message: "Cleaning up...", increment: 2 });
765
966
  } catch (err) {
766
- logger.error(`SDK install failed: ${err instanceof Error ? err.message : String(err)}`);
767
- fs8.rmSync(tmpDir, { recursive: true, force: true });
768
- throw err;
967
+ const wrapped = toSpaceError(err, tmpRoot, what);
968
+ logger.error(`SDK install failed: ${wrapped instanceof Error ? wrapped.message : String(wrapped)}`);
969
+ removeTempWorkDir(tmpDir, tmpRoot);
970
+ throw wrapped;
769
971
  }
770
972
  }
771
973
 
772
974
  // src/cmdTools/install.ts
773
- var fs9 = __toESM(require("fs"), 1);
975
+ var fs10 = __toESM(require("fs"), 1);
774
976
  var os6 = __toESM(require("os"), 1);
775
- var path8 = __toESM(require("path"), 1);
977
+ var path10 = __toESM(require("path"), 1);
776
978
  var import_node_child_process = require("child_process");
777
- function getCmdToolsDownloadUrl(config, platform6 = os6.platform()) {
778
- if (platform6 === "linux") {
979
+ function getCmdToolsDownloadUrl(config, platform7 = os6.platform()) {
980
+ if (platform7 === "linux") {
779
981
  return config.get("cmdToolsUrlLinux", defaultPaths.cmdToolsUrlLinux);
780
982
  }
781
- if (platform6 === "win32") {
983
+ if (platform7 === "win32") {
782
984
  const url = config.get("cmdToolsUrlWindows", "");
783
985
  if (!url) {
784
986
  throw new OniroError(
@@ -787,7 +989,7 @@ function getCmdToolsDownloadUrl(config, platform6 = os6.platform()) {
787
989
  }
788
990
  return url;
789
991
  }
790
- if (platform6 === "darwin") {
992
+ if (platform7 === "darwin") {
791
993
  const url = config.get("cmdToolsUrlMac", "");
792
994
  if (!url) {
793
995
  throw new OniroError(
@@ -796,20 +998,20 @@ function getCmdToolsDownloadUrl(config, platform6 = os6.platform()) {
796
998
  }
797
999
  return url;
798
1000
  }
799
- throw new UnsupportedPlatformError(platform6);
1001
+ throw new UnsupportedPlatformError(platform7);
800
1002
  }
801
1003
  function findCmdToolsSourceDir(extractPath) {
802
1004
  const known = [
803
- path8.join(extractPath, "command-line-tools"),
804
- path8.join(extractPath, "oh-command-line-tools"),
805
- path8.join(extractPath, "commandline-tools")
1005
+ path10.join(extractPath, "command-line-tools"),
1006
+ path10.join(extractPath, "oh-command-line-tools"),
1007
+ path10.join(extractPath, "commandline-tools")
806
1008
  ];
807
1009
  for (const c of known) {
808
- if (fs9.existsSync(c)) return c;
1010
+ if (fs10.existsSync(c)) return c;
809
1011
  }
810
- const entries = fs9.readdirSync(extractPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path8.join(extractPath, e.name));
1012
+ const entries = fs10.readdirSync(extractPath, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => path10.join(extractPath, e.name));
811
1013
  for (const dir of entries) {
812
- if (fs9.existsSync(path8.join(dir, "bin"))) return dir;
1014
+ if (fs10.existsSync(path10.join(dir, "bin"))) return dir;
813
1015
  }
814
1016
  throw new OniroError("Could not locate command line tools folder in the extracted archive.");
815
1017
  }
@@ -817,53 +1019,62 @@ async function installCmdTools(opts) {
817
1019
  const { config, progress, abortSignal } = opts;
818
1020
  const logger = opts.logger ?? noopLogger;
819
1021
  const CMD_PATH = getCmdToolsPath(config);
820
- const tmpDir = fs9.mkdtempSync(path8.join(os6.tmpdir(), "oniro-cmdtools-"));
821
- const zipPath = opts.localZipPath ?? path8.join(tmpDir, "oh-command-line-tools.zip");
822
- const extractPath = path8.join(tmpDir, "oh-command-line-tools");
1022
+ const what = "the command-line tools install";
1023
+ const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
1024
+ config,
1025
+ override: opts.tmpDir,
1026
+ installRoot: path10.dirname(CMD_PATH),
1027
+ prefix: "oniro-cmdtools-",
1028
+ logger
1029
+ });
1030
+ const zipPath = opts.localZipPath ?? path10.join(tmpDir, "oh-command-line-tools.zip");
1031
+ const extractPath = path10.join(tmpDir, "oh-command-line-tools");
823
1032
  try {
824
1033
  if (!opts.localZipPath) {
825
1034
  const url = getCmdToolsDownloadUrl(config);
826
1035
  progress?.report({ message: "Downloading command line tools...", increment: 0 });
827
- await downloadFile({ url, dest: zipPath, progress, abortSignal, start: 0, range: 50 });
1036
+ await downloadFile({ url, dest: zipPath, progress, abortSignal, start: 0, range: 50, what, tmpRoot });
828
1037
  }
829
1038
  progress?.report({ message: "Extracting tools...", increment: 0 });
830
1039
  await extractZipWithProgress({ zipPath, dest: extractPath, progress, start: 50, range: 45, logger });
831
- fs9.mkdirSync(CMD_PATH, { recursive: true });
1040
+ fs10.mkdirSync(CMD_PATH, { recursive: true });
832
1041
  const srcDir = findCmdToolsSourceDir(extractPath);
833
- for (const entry of fs9.readdirSync(srcDir)) {
834
- const src = path8.join(srcDir, entry);
835
- const dest = path8.join(CMD_PATH, entry);
836
- if (fs9.statSync(src).isDirectory()) {
837
- if (fs9.existsSync(dest)) fs9.rmSync(dest, { recursive: true, force: true });
1042
+ for (const entry of fs10.readdirSync(srcDir)) {
1043
+ const src = path10.join(srcDir, entry);
1044
+ const dest = path10.join(CMD_PATH, entry);
1045
+ if (fs10.statSync(src).isDirectory()) {
1046
+ if (fs10.existsSync(dest)) fs10.rmSync(dest, { recursive: true, force: true });
838
1047
  movePath(src, dest);
839
1048
  } else {
840
- fs9.copyFileSync(src, dest);
1049
+ fs10.copyFileSync(src, dest);
841
1050
  }
842
1051
  }
843
- const binDir = path8.join(CMD_PATH, "bin");
844
- if (fs9.existsSync(binDir) && os6.platform() !== "win32") {
845
- for (const file of fs9.readdirSync(binDir)) {
846
- fs9.chmodSync(path8.join(binDir, file), 493);
1052
+ const binDir = path10.join(CMD_PATH, "bin");
1053
+ if (fs10.existsSync(binDir) && os6.platform() !== "win32") {
1054
+ for (const file of fs10.readdirSync(binDir)) {
1055
+ fs10.chmodSync(path10.join(binDir, file), 493);
847
1056
  }
848
1057
  }
849
1058
  progress?.report({ message: "Finalizing installation...", increment: 5 });
850
1059
  progress?.report({ message: "Cleaning up...", increment: 0 });
1060
+ } catch (err) {
1061
+ throw toSpaceError(err, tmpRoot, what);
851
1062
  } finally {
852
- fs9.rmSync(tmpDir, { recursive: true, force: true });
1063
+ removeTempWorkDir(tmpDir, tmpRoot);
853
1064
  }
854
1065
  }
855
1066
  function getCmdToolsStatus(config) {
856
1067
  const cmdPath = getCmdToolsPath(config);
857
- const binDir = path8.join(cmdPath, "bin");
1068
+ const binDir = path10.join(cmdPath, "bin");
858
1069
  const candidates = os6.platform() === "win32" ? ["ohpm.exe", "ohpm.cmd", "ohpm.bat", "ohpm"] : ["ohpm"];
859
- const bin = candidates.map((c) => path8.join(binDir, c)).find((p) => fs9.existsSync(p));
1070
+ const bin = candidates.map((c) => path10.join(binDir, c)).find((p) => fs10.existsSync(p));
860
1071
  if (!bin) {
861
1072
  return { installed: false, status: "Not installed" };
862
1073
  }
863
1074
  try {
864
- const versionFile = path8.join(cmdPath, "version.txt");
865
- if (fs9.existsSync(versionFile)) {
866
- const content = fs9.readFileSync(versionFile, "utf8");
1075
+ const versionFile = path10.join(cmdPath, "version.txt");
1076
+ if (fs10.existsSync(versionFile)) {
1077
+ const content = fs10.readFileSync(versionFile, "utf8");
867
1078
  for (const line of content.split(/\r?\n/)) {
868
1079
  const m = line.match(/^\s*#\s*Version:\s*(.+)$/);
869
1080
  if (m?.[1]) return { installed: true, status: `Installed (${m[1].trim()})` };
@@ -883,14 +1094,14 @@ function isCmdToolsInstalled(config) {
883
1094
  }
884
1095
  function removeCmdTools(config) {
885
1096
  const cmdPath = getCmdToolsPath(config);
886
- if (fs9.existsSync(cmdPath)) {
887
- fs9.rmSync(cmdPath, { recursive: true, force: true });
1097
+ if (fs10.existsSync(cmdPath)) {
1098
+ fs10.rmSync(cmdPath, { recursive: true, force: true });
888
1099
  }
889
1100
  }
890
1101
 
891
1102
  // src/sign/encryptKey.ts
892
- var fs10 = __toESM(require("fs"), 1);
893
- var path9 = __toESM(require("path"), 1);
1103
+ var fs11 = __toESM(require("fs"), 1);
1104
+ var path11 = __toESM(require("path"), 1);
894
1105
  var crypto2 = __toESM(require("crypto"), 1);
895
1106
  var DAEMON_ROOT_KEY_COMPONENT_LENGTH = 16;
896
1107
  var DAEMON_SALT_KEY_LENGTH = 16;
@@ -962,33 +1173,33 @@ function getRootKey(fdComponents, salt) {
962
1173
  function createAndStoreKey(dir, keyLength) {
963
1174
  const key = crypto2.randomBytes(keyLength);
964
1175
  const hash = crypto2.createHash("sha256").update(key).digest("hex");
965
- const filePath = path9.join(dir, hash);
966
- fs10.writeFileSync(filePath, key);
967
- fs10.chmodSync(filePath, KEY_FILE_PERMISSIONS);
1176
+ const filePath = path11.join(dir, hash);
1177
+ fs11.writeFileSync(filePath, key);
1178
+ fs11.chmodSync(filePath, KEY_FILE_PERMISSIONS);
968
1179
  return key;
969
1180
  }
970
1181
  function createAndStoreEnKey(rootKey, ceDir) {
971
1182
  const workKey = crypto2.randomBytes(DAEMON_WORK_KEY_LENGTH);
972
1183
  const encrypted = encrypt(rootKey, workKey);
973
1184
  const hash = crypto2.createHash("sha256").update(encrypted).digest("hex");
974
- const filePath = path9.join(ceDir, hash);
975
- fs10.writeFileSync(filePath, encrypted);
976
- fs10.chmodSync(filePath, KEY_FILE_PERMISSIONS);
1185
+ const filePath = path11.join(ceDir, hash);
1186
+ fs11.writeFileSync(filePath, encrypted);
1187
+ fs11.chmodSync(filePath, KEY_FILE_PERMISSIONS);
977
1188
  }
978
1189
  function createMaterial(materialPath) {
979
- fs10.mkdirSync(materialPath, { recursive: true });
980
- fs10.chmodSync(materialPath, KEY_FILE_DIRECTORY_PERMISSIONS);
981
- const fdDir = path9.join(materialPath, "fd");
982
- const acDir = path9.join(materialPath, "ac");
983
- const ceDir = path9.join(materialPath, "ce");
984
- fs10.mkdirSync(fdDir, { recursive: true });
985
- fs10.mkdirSync(acDir, { recursive: true });
986
- fs10.mkdirSync(ceDir, { recursive: true });
1190
+ fs11.mkdirSync(materialPath, { recursive: true });
1191
+ fs11.chmodSync(materialPath, KEY_FILE_DIRECTORY_PERMISSIONS);
1192
+ const fdDir = path11.join(materialPath, "fd");
1193
+ const acDir = path11.join(materialPath, "ac");
1194
+ const ceDir = path11.join(materialPath, "ce");
1195
+ fs11.mkdirSync(fdDir, { recursive: true });
1196
+ fs11.mkdirSync(acDir, { recursive: true });
1197
+ fs11.mkdirSync(ceDir, { recursive: true });
987
1198
  const fdSubDirs = ["0", "1", "2"];
988
1199
  const fdComponents = [];
989
1200
  for (const sub of fdSubDirs) {
990
- const subDir = path9.join(fdDir, sub);
991
- fs10.mkdirSync(subDir, { recursive: true });
1201
+ const subDir = path11.join(fdDir, sub);
1202
+ fs11.mkdirSync(subDir, { recursive: true });
992
1203
  const comp = createAndStoreKey(subDir, DAEMON_ROOT_KEY_COMPONENT_LENGTH);
993
1204
  fdComponents.push(comp);
994
1205
  }
@@ -997,24 +1208,24 @@ function createMaterial(materialPath) {
997
1208
  createAndStoreEnKey(rootKey, ceDir);
998
1209
  }
999
1210
  function readSingleFile(dir) {
1000
- if (!fs10.existsSync(dir) || !fs10.statSync(dir).isDirectory()) {
1211
+ if (!fs11.existsSync(dir) || !fs11.statSync(dir).isDirectory()) {
1001
1212
  throw new Error(`Missing signing material directory: ${dir}`);
1002
1213
  }
1003
- const files = fs10.readdirSync(dir).filter((f) => f !== ".DS_Store");
1214
+ const files = fs11.readdirSync(dir).filter((f) => f !== ".DS_Store");
1004
1215
  if (files.length !== 1) {
1005
1216
  throw new Error(`Signing material in ${dir} is illegal (expected exactly one file).`);
1006
1217
  }
1007
- return fs10.readFileSync(path9.join(dir, files[0]));
1218
+ return fs11.readFileSync(path11.join(dir, files[0]));
1008
1219
  }
1009
1220
  function getKey(materialPath) {
1010
- if (!fs10.existsSync(materialPath) || !fs10.statSync(materialPath).isDirectory()) {
1221
+ if (!fs11.existsSync(materialPath) || !fs11.statSync(materialPath).isDirectory()) {
1011
1222
  throw new Error("Material directory does not exist.");
1012
1223
  }
1013
- const fdDir = path9.join(materialPath, "fd");
1014
- const fdComponents = ["0", "1", "2"].map((sub) => readSingleFile(path9.join(fdDir, sub)));
1015
- const salt = readSingleFile(path9.join(materialPath, "ac"));
1224
+ const fdDir = path11.join(materialPath, "fd");
1225
+ const fdComponents = ["0", "1", "2"].map((sub) => readSingleFile(path11.join(fdDir, sub)));
1226
+ const salt = readSingleFile(path11.join(materialPath, "ac"));
1016
1227
  const rootKey = getRootKey(fdComponents, salt);
1017
- const workMaterial = readSingleFile(path9.join(materialPath, "ce"));
1228
+ const workMaterial = readSingleFile(path11.join(materialPath, "ce"));
1018
1229
  return decrypt(rootKey, workMaterial);
1019
1230
  }
1020
1231
  function encryptPwd(password, materialPath) {
@@ -1029,8 +1240,8 @@ function decryptPwd(encryptedHex, materialPath) {
1029
1240
  }
1030
1241
 
1031
1242
  // src/sign/generateSigningConfigs.ts
1032
- var fs11 = __toESM(require("fs"), 1);
1033
- var path10 = __toESM(require("path"), 1);
1243
+ var fs12 = __toESM(require("fs"), 1);
1244
+ var path12 = __toESM(require("path"), 1);
1034
1245
  var import_node_child_process2 = require("child_process");
1035
1246
  var import_json52 = __toESM(require("json5"), 1);
1036
1247
 
@@ -1100,17 +1311,17 @@ var SIGNING_KIND_CONFIG = {
1100
1311
  };
1101
1312
  function copyFilesToProject(projectDir, paths, kind, logger, applicationCertPath) {
1102
1313
  logger.info("[sign] Copying signing material into project...");
1103
- const signaturesDir = path10.join(projectDir, "signatures");
1104
- fs11.mkdirSync(signaturesDir, { recursive: true });
1105
- fs11.copyFileSync(paths.keystore, path10.join(signaturesDir, "OpenHarmony.p12"));
1106
- fs11.copyFileSync(paths.profileCert, path10.join(signaturesDir, "OpenHarmonyProfileRelease.pem"));
1107
- fs11.copyFileSync(paths.unsignedProfileTemplate, path10.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json"));
1314
+ const signaturesDir = path12.join(projectDir, "signatures");
1315
+ fs12.mkdirSync(signaturesDir, { recursive: true });
1316
+ fs12.copyFileSync(paths.keystore, path12.join(signaturesDir, "OpenHarmony.p12"));
1317
+ fs12.copyFileSync(paths.profileCert, path12.join(signaturesDir, "OpenHarmonyProfileRelease.pem"));
1318
+ fs12.copyFileSync(paths.unsignedProfileTemplate, path12.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json"));
1108
1319
  if (kind === "application-release") {
1109
- const dest = path10.join(signaturesDir, "OpenHarmonyApplication.cer");
1320
+ const dest = path12.join(signaturesDir, "OpenHarmonyApplication.cer");
1110
1321
  if (applicationCertPath) {
1111
- fs11.copyFileSync(applicationCertPath, dest);
1322
+ fs12.copyFileSync(applicationCertPath, dest);
1112
1323
  } else {
1113
- fs11.writeFileSync(dest, OPEN_HARMONY_APPLICATION_CERT);
1324
+ fs12.writeFileSync(dest, OPEN_HARMONY_APPLICATION_CERT);
1114
1325
  }
1115
1326
  }
1116
1327
  }
@@ -1119,7 +1330,7 @@ function resolveAppFeature(apl, override) {
1119
1330
  return apl === "normal" ? "hos_normal_app" : "hos_system_app";
1120
1331
  }
1121
1332
  function extractLeafCertificate(chainPath) {
1122
- const certContent = fs11.readFileSync(chainPath, "utf-8");
1333
+ const certContent = fs12.readFileSync(chainPath, "utf-8");
1123
1334
  const parts = certContent.split("-----END CERTIFICATE-----");
1124
1335
  if (parts.length < 3) {
1125
1336
  throw new OniroError(`${chainPath} does not contain enough certificates.`);
@@ -1129,20 +1340,20 @@ function extractLeafCertificate(chainPath) {
1129
1340
  function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}) {
1130
1341
  const kind = options.kind ?? pickSigningKind(apl);
1131
1342
  logger.info(`[sign] Modifying profile template (apl=${apl}, app-feature=${appFeature}, kind=${kind})...`);
1132
- const appJsonPath = path10.join(projectDir, "AppScope/app.json5");
1133
- const profileTemplatePath = path10.join(projectDir, "signatures/UnsgnedReleasedProfileTemplate.json");
1134
- if (!fs11.existsSync(appJsonPath)) {
1343
+ const appJsonPath = path12.join(projectDir, "AppScope/app.json5");
1344
+ const profileTemplatePath = path12.join(projectDir, "signatures/UnsgnedReleasedProfileTemplate.json");
1345
+ if (!fs12.existsSync(appJsonPath)) {
1135
1346
  throw new OniroError(`${appJsonPath} does not exist.`);
1136
1347
  }
1137
1348
  let appJson;
1138
1349
  try {
1139
- appJson = import_json52.default.parse(fs11.readFileSync(appJsonPath, "utf-8"));
1350
+ appJson = import_json52.default.parse(fs12.readFileSync(appJsonPath, "utf-8"));
1140
1351
  } catch (e) {
1141
1352
  throw new OniroError(`Error parsing ${appJsonPath}: ${e.message}`, e);
1142
1353
  }
1143
1354
  let profileTemplate;
1144
1355
  try {
1145
- profileTemplate = JSON.parse(fs11.readFileSync(profileTemplatePath, "utf-8"));
1356
+ profileTemplate = JSON.parse(fs12.readFileSync(profileTemplatePath, "utf-8"));
1146
1357
  } catch (e) {
1147
1358
  throw new OniroError(`Error parsing ${profileTemplatePath}: ${e.message}`, e);
1148
1359
  }
@@ -1155,7 +1366,7 @@ function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}
1155
1366
  profileTemplate["bundle-info"]["bundle-name"] = appJson.app.bundleName;
1156
1367
  profileTemplate["bundle-info"]["apl"] = apl;
1157
1368
  profileTemplate["bundle-info"]["app-feature"] = appFeature;
1158
- const distCertChainPath = path10.join(
1369
+ const distCertChainPath = path12.join(
1159
1370
  projectDir,
1160
1371
  "signatures",
1161
1372
  SIGNING_KIND_CONFIG[kind].certBasename
@@ -1165,13 +1376,13 @@ function modifyProfileTemplate(projectDir, apl, appFeature, logger, options = {}
1165
1376
  profileTemplate.acls = profileTemplate.acls ?? {};
1166
1377
  profileTemplate.acls["allowed-acls"] = options.acls;
1167
1378
  }
1168
- fs11.writeFileSync(profileTemplatePath, JSON.stringify(profileTemplate, null, 2));
1379
+ fs12.writeFileSync(profileTemplatePath, JSON.stringify(profileTemplate, null, 2));
1169
1380
  }
1170
1381
  function generateP7bFile(projectDir, paths, logger, passwords) {
1171
1382
  logger.info("[sign] Generating P7b profile via hap-sign-tool...");
1172
- const signaturesDir = path10.join(projectDir, "signatures");
1173
- const profileTemplatePath = path10.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json");
1174
- const outputProfilePath = path10.join(signaturesDir, "app1-profile.p7b");
1383
+ const signaturesDir = path12.join(projectDir, "signatures");
1384
+ const profileTemplatePath = path12.join(signaturesDir, "UnsgnedReleasedProfileTemplate.json");
1385
+ const outputProfilePath = path12.join(signaturesDir, "app1-profile.p7b");
1175
1386
  const args = [
1176
1387
  "-jar",
1177
1388
  paths.signTool,
@@ -1205,11 +1416,11 @@ function generateP7bFile(projectDir, paths, logger, passwords) {
1205
1416
  }
1206
1417
  }
1207
1418
  function detectSigningConfigNames(projectDir) {
1208
- const buildProfilePath = path10.join(projectDir, "build-profile.json5");
1209
- if (!fs11.existsSync(buildProfilePath)) return ["default"];
1419
+ const buildProfilePath = path12.join(projectDir, "build-profile.json5");
1420
+ if (!fs12.existsSync(buildProfilePath)) return ["default"];
1210
1421
  let parsed;
1211
1422
  try {
1212
- parsed = import_json52.default.parse(fs11.readFileSync(buildProfilePath, "utf-8"));
1423
+ parsed = import_json52.default.parse(fs12.readFileSync(buildProfilePath, "utf-8"));
1213
1424
  } catch {
1214
1425
  return ["default"];
1215
1426
  }
@@ -1226,14 +1437,14 @@ function detectSigningConfigNames(projectDir) {
1226
1437
  }
1227
1438
  function updateBuildProfile(projectDir, kind, logger, passwords) {
1228
1439
  logger.info("[sign] Writing signing configs into build-profile.json5...");
1229
- const materialDir = path10.join(projectDir, "signatures", "material");
1230
- const buildProfilePath = path10.join(projectDir, "build-profile.json5");
1440
+ const materialDir = path12.join(projectDir, "signatures", "material");
1441
+ const buildProfilePath = path12.join(projectDir, "build-profile.json5");
1231
1442
  const encryptedStorePassword = encryptPwd(passwords.store, materialDir);
1232
1443
  const encryptedKeyPassword = encryptPwd(passwords.key, materialDir);
1233
1444
  let buildProfile = { app: {} };
1234
- if (fs11.existsSync(buildProfilePath)) {
1445
+ if (fs12.existsSync(buildProfilePath)) {
1235
1446
  try {
1236
- buildProfile = import_json52.default.parse(fs11.readFileSync(buildProfilePath, "utf-8"));
1447
+ buildProfile = import_json52.default.parse(fs12.readFileSync(buildProfilePath, "utf-8"));
1237
1448
  } catch (e) {
1238
1449
  throw new OniroError(`Error parsing ${buildProfilePath}: ${e.message}`, e);
1239
1450
  }
@@ -1254,13 +1465,13 @@ function updateBuildProfile(projectDir, kind, logger, passwords) {
1254
1465
  storeFile: "./signatures/OpenHarmony.p12"
1255
1466
  }
1256
1467
  }));
1257
- fs11.writeFileSync(buildProfilePath, JSON.stringify(buildProfile, null, 2));
1468
+ fs12.writeFileSync(buildProfilePath, JSON.stringify(buildProfile, null, 2));
1258
1469
  }
1259
1470
  function prepareMaterialDirectory(projectDir, logger) {
1260
1471
  logger.info("[sign] Generating fresh signing material...");
1261
- const materialDir = path10.join(projectDir, "signatures", "material");
1262
- if (fs11.existsSync(materialDir)) {
1263
- fs11.rmSync(materialDir, { recursive: true, force: true });
1472
+ const materialDir = path12.join(projectDir, "signatures", "material");
1473
+ if (fs12.existsSync(materialDir)) {
1474
+ fs12.rmSync(materialDir, { recursive: true, force: true });
1264
1475
  }
1265
1476
  createMaterial(materialDir);
1266
1477
  }
@@ -1283,15 +1494,15 @@ function generateSigningConfigs(options) {
1283
1494
  "Could not detect project SDK version (compileSdkVersion missing in build-profile.json5)."
1284
1495
  );
1285
1496
  }
1286
- const sdkPath = path10.join(sdkHome, String(sdkVersion));
1287
- if (!fs11.existsSync(sdkPath)) {
1497
+ const sdkPath = path12.join(sdkHome, String(sdkVersion));
1498
+ if (!fs12.existsSync(sdkPath)) {
1288
1499
  throw new OniroError(`SDK path does not exist: ${sdkPath}`);
1289
1500
  }
1290
1501
  const paths = {
1291
- signTool: path10.join(sdkPath, "toolchains/lib/hap-sign-tool.jar"),
1292
- keystore: path10.join(sdkPath, "toolchains/lib/OpenHarmony.p12"),
1293
- profileCert: path10.join(sdkPath, "toolchains/lib/OpenHarmonyProfileRelease.pem"),
1294
- unsignedProfileTemplate: path10.join(sdkPath, "toolchains/lib/UnsgnedReleasedProfileTemplate.json")
1502
+ signTool: path12.join(sdkPath, "toolchains/lib/hap-sign-tool.jar"),
1503
+ keystore: path12.join(sdkPath, "toolchains/lib/OpenHarmony.p12"),
1504
+ profileCert: path12.join(sdkPath, "toolchains/lib/OpenHarmonyProfileRelease.pem"),
1505
+ unsignedProfileTemplate: path12.join(sdkPath, "toolchains/lib/UnsgnedReleasedProfileTemplate.json")
1295
1506
  };
1296
1507
  const kind = pickSigningKind(apl);
1297
1508
  const passwords = options.passwords ?? DEFAULT_PASSWORDS;
@@ -1305,46 +1516,54 @@ function generateSigningConfigs(options) {
1305
1516
  }
1306
1517
 
1307
1518
  // src/emulator/install.ts
1308
- var fs12 = __toESM(require("fs"), 1);
1309
- var os7 = __toESM(require("os"), 1);
1310
- var path11 = __toESM(require("path"), 1);
1519
+ var fs13 = __toESM(require("fs"), 1);
1520
+ var path13 = __toESM(require("path"), 1);
1311
1521
  async function installEmulator(opts) {
1312
1522
  const { config, progress, abortSignal } = opts;
1313
1523
  const logger = opts.logger ?? noopLogger;
1314
1524
  const url = config.get("emulatorUrl", defaultPaths.emulatorUrl);
1315
1525
  const emulatorDir = getEmulatorDir(config);
1316
- const tmpDir = fs12.mkdtempSync(path11.join(os7.tmpdir(), "oniro-emulator-"));
1317
- const tmpZip = path11.join(tmpDir, "oniro_emulator.zip");
1526
+ const what = "the emulator install";
1527
+ const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
1528
+ config,
1529
+ override: opts.tmpDir,
1530
+ installRoot: path13.dirname(emulatorDir),
1531
+ prefix: "oniro-emulator-",
1532
+ logger
1533
+ });
1534
+ const tmpZip = path13.join(tmpDir, "oniro_emulator.zip");
1318
1535
  try {
1319
- fs12.mkdirSync(emulatorDir, { recursive: true });
1536
+ fs13.mkdirSync(emulatorDir, { recursive: true });
1320
1537
  progress?.report({ message: "Downloading emulator...", increment: 0 });
1321
- await downloadFile({ url, dest: tmpZip, progress, abortSignal, start: 0, range: 50 });
1538
+ await downloadFile({ url, dest: tmpZip, progress, abortSignal, start: 0, range: 50, what, tmpRoot });
1322
1539
  progress?.report({ message: "Extracting emulator...", increment: 0 });
1323
1540
  await extractZipWithProgress({ zipPath: tmpZip, dest: emulatorDir, progress, start: 50, range: 45, logger });
1324
- const runSh = path11.join(emulatorDir, "images", "run.sh");
1325
- if (fs12.existsSync(runSh)) {
1326
- fs12.chmodSync(runSh, 493);
1541
+ const runSh = path13.join(emulatorDir, "images", "run.sh");
1542
+ if (fs13.existsSync(runSh)) {
1543
+ fs13.chmodSync(runSh, 493);
1327
1544
  }
1328
1545
  progress?.report({ message: "Finalizing installation...", increment: 5 });
1546
+ } catch (err) {
1547
+ throw toSpaceError(err, tmpRoot, what);
1329
1548
  } finally {
1330
- fs12.rmSync(tmpDir, { recursive: true, force: true });
1549
+ removeTempWorkDir(tmpDir, tmpRoot);
1331
1550
  }
1332
1551
  }
1333
1552
  function isEmulatorInstalled(config) {
1334
- const imagesDir = path11.join(getEmulatorDir(config), "images");
1335
- return fs12.existsSync(path11.join(imagesDir, "run.sh")) || fs12.existsSync(path11.join(imagesDir, "run.bat"));
1553
+ const imagesDir = path13.join(getEmulatorDir(config), "images");
1554
+ return fs13.existsSync(path13.join(imagesDir, "run.sh")) || fs13.existsSync(path13.join(imagesDir, "run.bat"));
1336
1555
  }
1337
1556
  function removeEmulator(config) {
1338
1557
  const emulatorDir = getEmulatorDir(config);
1339
- if (fs12.existsSync(emulatorDir)) {
1340
- fs12.rmSync(emulatorDir, { recursive: true, force: true });
1558
+ if (fs13.existsSync(emulatorDir)) {
1559
+ fs13.rmSync(emulatorDir, { recursive: true, force: true });
1341
1560
  }
1342
1561
  }
1343
1562
 
1344
1563
  // src/emulator/lifecycle.ts
1345
- var fs13 = __toESM(require("fs"), 1);
1346
- var os8 = __toESM(require("os"), 1);
1347
- var path12 = __toESM(require("path"), 1);
1564
+ var fs14 = __toESM(require("fs"), 1);
1565
+ var os7 = __toESM(require("os"), 1);
1566
+ var path14 = __toESM(require("path"), 1);
1348
1567
  var import_node_child_process4 = require("child_process");
1349
1568
 
1350
1569
  // src/hdc/exec.ts
@@ -1353,7 +1572,7 @@ function runProcess(opts) {
1353
1572
  const { command, args, cwd, env, onOutput } = opts;
1354
1573
  const timeoutMs = opts.timeoutMs ?? 6e4;
1355
1574
  const { abortSignal } = opts;
1356
- return new Promise((resolve2, reject) => {
1575
+ return new Promise((resolve4, reject) => {
1357
1576
  if (abortSignal?.aborted) {
1358
1577
  reject(new CancelledError(`Command aborted before start: ${command}`));
1359
1578
  return;
@@ -1414,7 +1633,7 @@ ${stderr.trim()}` : "")
1414
1633
  );
1415
1634
  return;
1416
1635
  }
1417
- resolve2({ code: code ?? -1, stdout, stderr });
1636
+ resolve4({ code: code ?? -1, stdout, stderr });
1418
1637
  });
1419
1638
  });
1420
1639
  }
@@ -1440,9 +1659,29 @@ function ensureOk(result, command) {
1440
1659
  }
1441
1660
  return result;
1442
1661
  }
1662
+ var REMOTE_RC_RE = /__ONIRO_RC=(-?\d+)__/g;
1663
+ function parseRemoteExit(stdout) {
1664
+ let code = null;
1665
+ for (const m of stdout.matchAll(REMOTE_RC_RE)) code = Number(m[1]);
1666
+ if (code === null) return null;
1667
+ return { code, stdout: stdout.replace(REMOTE_RC_RE, "").replace(/[ \t\r\n]+$/, "") };
1668
+ }
1669
+ async function shellChecked(opts) {
1670
+ const { command, ...rest } = opts;
1671
+ const res = await hdcExec({ ...rest, args: ["shell", `${command}; echo "__ONIRO_RC=$?__"`] });
1672
+ const parsed = parseRemoteExit(res.stdout);
1673
+ if (!parsed) return res;
1674
+ return { code: parsed.code, stdout: parsed.stdout, stderr: res.stderr };
1675
+ }
1676
+ function ensureRemoteOk(result, command) {
1677
+ if (result.code !== 0) {
1678
+ throw new CommandFailedError(command, result.code, result.stderr.trim() || result.stdout.trim());
1679
+ }
1680
+ return result;
1681
+ }
1443
1682
 
1444
1683
  // src/emulator/lifecycle.ts
1445
- var PID_FILE = path12.join(os8.tmpdir(), "oniro_emulator.pid");
1684
+ var PID_FILE = path14.join(os7.tmpdir(), "oniro_emulator.pid");
1446
1685
  async function attemptHdcConnection(config, address = "127.0.0.1:55555", logger = noopLogger) {
1447
1686
  try {
1448
1687
  await hdcExec({ config, args: ["start", "-r"], logger });
@@ -1455,24 +1694,24 @@ async function attemptHdcConnection(config, address = "127.0.0.1:55555", logger
1455
1694
  }
1456
1695
  }
1457
1696
  function resolveLauncher(imagesPath, headless, connect) {
1458
- const runSh = path12.join(imagesPath, "run.sh");
1459
- const runBat = path12.join(imagesPath, "run.bat");
1697
+ const runSh = path14.join(imagesPath, "run.sh");
1698
+ const runBat = path14.join(imagesPath, "run.bat");
1460
1699
  const extra = [];
1461
1700
  if (headless) extra.push("--headless");
1462
1701
  if (connect) extra.push("--connect", connect);
1463
- if (os8.platform() === "win32") {
1464
- if (fs13.existsSync(runBat)) {
1702
+ if (os7.platform() === "win32") {
1703
+ if (fs14.existsSync(runBat)) {
1465
1704
  return { command: "cmd.exe", args: ["/c", runBat, ...extra], cwd: imagesPath };
1466
1705
  }
1467
- if (fs13.existsSync(runSh)) {
1706
+ if (fs14.existsSync(runSh)) {
1468
1707
  return { command: "bash", args: [runSh, ...extra], cwd: imagesPath };
1469
1708
  }
1470
1709
  throw new OniroError(`No emulator launcher (run.bat or run.sh) found in ${imagesPath}.`);
1471
1710
  }
1472
- if (fs13.existsSync(runSh)) {
1711
+ if (fs14.existsSync(runSh)) {
1473
1712
  return { command: "bash", args: [runSh, ...extra], cwd: imagesPath };
1474
1713
  }
1475
- if (fs13.existsSync(runBat)) {
1714
+ if (fs14.existsSync(runBat)) {
1476
1715
  return { command: "bash", args: [runBat, ...extra], cwd: imagesPath };
1477
1716
  }
1478
1717
  throw new OniroError(`No emulator launcher (run.sh or run.bat) found in ${imagesPath}.`);
@@ -1480,9 +1719,9 @@ function resolveLauncher(imagesPath, headless, connect) {
1480
1719
  async function startEmulator(opts) {
1481
1720
  const { config } = opts;
1482
1721
  const logger = opts.logger ?? noopLogger;
1483
- if (os8.platform() !== "win32" && fs13.existsSync(PID_FILE)) {
1722
+ if (os7.platform() !== "win32" && fs14.existsSync(PID_FILE)) {
1484
1723
  try {
1485
- const pid = Number(fs13.readFileSync(PID_FILE, "utf8").trim());
1724
+ const pid = Number(fs14.readFileSync(PID_FILE, "utf8").trim());
1486
1725
  if (Number.isFinite(pid) && pid > 0) {
1487
1726
  try {
1488
1727
  process.kill(pid, 0);
@@ -1498,13 +1737,13 @@ async function startEmulator(opts) {
1498
1737
  logger.warn(`Could not read PID file: ${err.message}`);
1499
1738
  }
1500
1739
  }
1501
- const imagesPath = path12.join(getEmulatorDir(config), "images");
1502
- if (!fs13.existsSync(imagesPath)) {
1740
+ const imagesPath = path14.join(getEmulatorDir(config), "images");
1741
+ if (!fs14.existsSync(imagesPath)) {
1503
1742
  throw new OniroError(`Emulator images directory not found at ${imagesPath}. Run \`oniro-app emulator install\` first.`);
1504
1743
  }
1505
1744
  const launcher = resolveLauncher(imagesPath, opts.headless === true, opts.connect);
1506
- const logPath = opts.logFile ?? (os8.platform() === "win32" ? "NUL" : "/dev/null");
1507
- const logFd = fs13.openSync(logPath, "a");
1745
+ const logPath = opts.logFile ?? (os7.platform() === "win32" ? "NUL" : "/dev/null");
1746
+ const logFd = fs14.openSync(logPath, "a");
1508
1747
  let child;
1509
1748
  try {
1510
1749
  child = (0, import_node_child_process4.spawn)(launcher.command, [...launcher.args], {
@@ -1514,19 +1753,19 @@ async function startEmulator(opts) {
1514
1753
  windowsHide: true
1515
1754
  });
1516
1755
  } finally {
1517
- fs13.closeSync(logFd);
1756
+ fs14.closeSync(logFd);
1518
1757
  }
1519
1758
  if (!child.pid) {
1520
1759
  throw new OniroError(`Failed to spawn launcher (${launcher.command} ${launcher.args.join(" ")}).`);
1521
1760
  }
1522
- fs13.writeFileSync(PID_FILE, String(child.pid));
1761
+ fs14.writeFileSync(PID_FILE, String(child.pid));
1523
1762
  child.unref();
1524
1763
  logger.info(`Emulator launched (PID ${child.pid}). Logs: ${logPath}`);
1525
- const earlyExit = new Promise((resolve2) => {
1526
- child.once("exit", (code) => resolve2(code));
1527
- child.once("error", () => resolve2(-1));
1764
+ const earlyExit = new Promise((resolve4) => {
1765
+ child.once("exit", (code) => resolve4(code));
1766
+ child.once("error", () => resolve4(-1));
1528
1767
  });
1529
- const liveness = new Promise((resolve2) => setTimeout(() => resolve2("alive"), 2e3));
1768
+ const liveness = new Promise((resolve4) => setTimeout(() => resolve4("alive"), 2e3));
1530
1769
  const outcome = await Promise.race([earlyExit, liveness]);
1531
1770
  if (outcome !== "alive") {
1532
1771
  const tail = readTail(logPath, 4e3);
@@ -1566,24 +1805,24 @@ ${tail}` : ""}`);
1566
1805
  }
1567
1806
  function readTail(filePath, bytes) {
1568
1807
  try {
1569
- const stat = fs13.statSync(filePath);
1808
+ const stat = fs14.statSync(filePath);
1570
1809
  const start = Math.max(0, stat.size - bytes);
1571
- const fd = fs13.openSync(filePath, "r");
1810
+ const fd = fs14.openSync(filePath, "r");
1572
1811
  try {
1573
1812
  const buf = Buffer.alloc(stat.size - start);
1574
- fs13.readSync(fd, buf, 0, buf.length, start);
1813
+ fs14.readSync(fd, buf, 0, buf.length, start);
1575
1814
  return buf.toString("utf8");
1576
1815
  } finally {
1577
- fs13.closeSync(fd);
1816
+ fs14.closeSync(fd);
1578
1817
  }
1579
1818
  } catch {
1580
1819
  return "";
1581
1820
  }
1582
1821
  }
1583
1822
  async function stopEmulator(logger = noopLogger) {
1584
- if (fs13.existsSync(PID_FILE)) {
1823
+ if (fs14.existsSync(PID_FILE)) {
1585
1824
  try {
1586
- const pid = Number(fs13.readFileSync(PID_FILE, "utf8").trim());
1825
+ const pid = Number(fs14.readFileSync(PID_FILE, "utf8").trim());
1587
1826
  if (Number.isFinite(pid) && pid > 0) {
1588
1827
  try {
1589
1828
  process.kill(pid, "SIGTERM");
@@ -1596,13 +1835,13 @@ async function stopEmulator(logger = noopLogger) {
1596
1835
  logger.warn(`Could not read PID file: ${err.message}`);
1597
1836
  }
1598
1837
  }
1599
- const [killCmd, ...killArgs] = os8.platform() === "win32" ? ["taskkill", "/IM", "qemu-system-x86_64.exe", "/F"] : ["pkill", "-f", "qemu-system-x86_64"];
1838
+ const [killCmd, ...killArgs] = os7.platform() === "win32" ? ["taskkill", "/IM", "qemu-system-x86_64.exe", "/F"] : ["pkill", "-f", "qemu-system-x86_64"];
1600
1839
  try {
1601
1840
  await runProcess({ command: killCmd, args: killArgs, logger });
1602
1841
  } catch (err) {
1603
1842
  logger.warn(`[emulator] could not run ${killCmd}: ${err.message}`);
1604
1843
  }
1605
- fs13.rm(PID_FILE, { force: true }, (err) => {
1844
+ fs14.rm(PID_FILE, { force: true }, (err) => {
1606
1845
  if (err) logger.warn(`Could not remove PID file: ${err.message}`);
1607
1846
  });
1608
1847
  }
@@ -1725,7 +1964,7 @@ async function getDisplaySize(config, opts = {}) {
1725
1964
 
1726
1965
  // src/hdc/wait.ts
1727
1966
  function delay(ms, signal) {
1728
- return new Promise((resolve2, reject) => {
1967
+ return new Promise((resolve4, reject) => {
1729
1968
  if (signal?.aborted) {
1730
1969
  reject(new CancelledError("Wait cancelled."));
1731
1970
  return;
@@ -1740,7 +1979,7 @@ function delay(ms, signal) {
1740
1979
  };
1741
1980
  const timer = setTimeout(() => {
1742
1981
  cleanup();
1743
- resolve2();
1982
+ resolve4();
1744
1983
  }, ms);
1745
1984
  signal?.addEventListener("abort", onAbort, { once: true });
1746
1985
  });
@@ -1769,21 +2008,21 @@ async function waitForCondition(opts) {
1769
2008
  }
1770
2009
 
1771
2010
  // src/hdc/app.ts
1772
- var fs15 = __toESM(require("fs"), 1);
1773
- var path14 = __toESM(require("path"), 1);
2011
+ var fs16 = __toESM(require("fs"), 1);
2012
+ var path16 = __toESM(require("path"), 1);
1774
2013
  var import_node_child_process5 = require("child_process");
1775
2014
 
1776
2015
  // src/hdc/project.ts
1777
- var fs14 = __toESM(require("fs"), 1);
1778
- var path13 = __toESM(require("path"), 1);
2016
+ var fs15 = __toESM(require("fs"), 1);
2017
+ var path15 = __toESM(require("path"), 1);
1779
2018
  var import_json53 = __toESM(require("json5"), 1);
1780
2019
  function readJson5(filePath) {
1781
- const content = fs14.readFileSync(filePath, "utf-8");
2020
+ const content = fs15.readFileSync(filePath, "utf-8");
1782
2021
  return import_json53.default.parse(content);
1783
2022
  }
1784
2023
  function getBundleName(projectDir) {
1785
- const appJsonPath = path13.join(projectDir, "AppScope", "app.json5");
1786
- if (!fs14.existsSync(appJsonPath)) {
2024
+ const appJsonPath = path15.join(projectDir, "AppScope", "app.json5");
2025
+ if (!fs15.existsSync(appJsonPath)) {
1787
2026
  throw new OniroError(`Could not find app.json5 at ${appJsonPath}`);
1788
2027
  }
1789
2028
  const appJson = readJson5(appJsonPath);
@@ -1793,8 +2032,8 @@ function getBundleName(projectDir) {
1793
2032
  return appJson.app.bundleName;
1794
2033
  }
1795
2034
  function getMainAbility(projectDir, moduleName = "entry", abilityName) {
1796
- const moduleJsonPath = path13.join(projectDir, moduleName, "src", "main", "module.json5");
1797
- if (!fs14.existsSync(moduleJsonPath)) {
2035
+ const moduleJsonPath = path15.join(projectDir, moduleName, "src", "main", "module.json5");
2036
+ if (!fs15.existsSync(moduleJsonPath)) {
1798
2037
  throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
1799
2038
  }
1800
2039
  const moduleJson = readJson5(moduleJsonPath);
@@ -1817,8 +2056,8 @@ function getMainAbility(projectDir, moduleName = "entry", abilityName) {
1817
2056
  async function installApp(opts) {
1818
2057
  const logger = scopedLogger(opts.logger ?? noopLogger, "hdc");
1819
2058
  const relativeHapPath = opts.hapPath ?? opts.config.get("hapPath", defaultPaths.hapPath);
1820
- const hapPath = path14.isAbsolute(relativeHapPath) ? relativeHapPath : path14.join(opts.projectDir, relativeHapPath);
1821
- if (!fs15.existsSync(hapPath)) {
2059
+ const hapPath = path16.isAbsolute(relativeHapPath) ? relativeHapPath : path16.join(opts.projectDir, relativeHapPath);
2060
+ if (!fs16.existsSync(hapPath)) {
1822
2061
  throw new OniroError(`HAP file not found at: ${hapPath}. Build and sign the app first.`);
1823
2062
  }
1824
2063
  const result = await hdcExec({ config: opts.config, args: ["install", hapPath], timeoutMs: 3e5 });
@@ -1835,13 +2074,59 @@ async function installApp(opts) {
1835
2074
  function detectAaStartFailure(output) {
1836
2075
  return /failed to start ability|Error Code:\s*\d|Error Message:/i.test(output) ? output.trim() : null;
1837
2076
  }
2077
+ function parseMainAbilityFromBmDump(stdout) {
2078
+ const start = stdout.indexOf("{");
2079
+ if (start < 0) return null;
2080
+ let info;
2081
+ try {
2082
+ info = JSON.parse(stdout.slice(start));
2083
+ } catch {
2084
+ return null;
2085
+ }
2086
+ const mods = Array.isArray(info?.hapModuleInfos) ? info.hapModuleInfos : [];
2087
+ const abilityOf = (m) => m?.mainElementName || m?.mainAbility || void 0;
2088
+ const isEntry = (m) => m?.moduleType === 1 || m?.moduleType === "1" || m?.moduleType === "entry";
2089
+ const entry = mods.find((m) => isEntry(m) && abilityOf(m));
2090
+ const any = mods.find((m) => abilityOf(m));
2091
+ return entry && abilityOf(entry) || any && abilityOf(any) || null;
2092
+ }
2093
+ async function resolveInstalledMainAbility(opts) {
2094
+ const res = await shell({
2095
+ config: opts.config,
2096
+ command: `bm dump -n ${opts.bundle}`,
2097
+ deviceSerial: opts.deviceSerial,
2098
+ timeoutMs: 15e3,
2099
+ logger: opts.logger
2100
+ });
2101
+ const ability = parseMainAbilityFromBmDump(res.stdout);
2102
+ if (!ability) {
2103
+ throw new OniroError(
2104
+ `Could not determine the main ability for installed bundle ${opts.bundle} (is it installed?). Pass an explicit ability instead.`
2105
+ );
2106
+ }
2107
+ return ability;
2108
+ }
1838
2109
  async function launchApp(opts) {
1839
2110
  const logger = scopedLogger(opts.logger ?? noopLogger, "hdc");
1840
- const bundleName = getBundleName(opts.projectDir);
1841
- const mainAbility = getMainAbility(opts.projectDir, opts.moduleName, opts.abilityName);
2111
+ let bundleName;
2112
+ let mainAbility;
2113
+ if (opts.bundleName) {
2114
+ bundleName = opts.bundleName;
2115
+ mainAbility = opts.abilityName ?? await resolveInstalledMainAbility({
2116
+ config: opts.config,
2117
+ bundle: bundleName,
2118
+ deviceSerial: opts.deviceSerial,
2119
+ logger: opts.logger
2120
+ });
2121
+ } else {
2122
+ if (!opts.projectDir) throw new OniroError("launchApp requires either bundleName or projectDir.");
2123
+ bundleName = getBundleName(opts.projectDir);
2124
+ mainAbility = getMainAbility(opts.projectDir, opts.moduleName, opts.abilityName);
2125
+ }
1842
2126
  const result = await hdcExec({
1843
2127
  config: opts.config,
1844
- args: ["shell", "aa", "start", "-a", mainAbility, "-b", bundleName]
2128
+ args: ["shell", "aa", "start", "-a", mainAbility, "-b", bundleName],
2129
+ deviceSerial: opts.deviceSerial
1845
2130
  });
1846
2131
  if (result.stdout.trim()) logger.info(result.stdout.trim());
1847
2132
  if (result.stderr.trim()) logger.warn(result.stderr.trim());
@@ -1856,7 +2141,7 @@ function listRunningProcesses(config, options = {}) {
1856
2141
  const logger = options.logger ?? noopLogger;
1857
2142
  const timeoutMs = options.timeoutMs ?? 1e3;
1858
2143
  const hdc = getHdcPath(config);
1859
- return new Promise((resolve2, reject) => {
2144
+ return new Promise((resolve4, reject) => {
1860
2145
  const proc = (0, import_node_child_process5.spawn)(hdc, ["track-jpid"]);
1861
2146
  const processes = [];
1862
2147
  let resolved = false;
@@ -1870,7 +2155,7 @@ function listRunningProcesses(config, options = {}) {
1870
2155
  if (options.targetProcessName && name === options.targetProcessName && !resolved) {
1871
2156
  resolved = true;
1872
2157
  proc.kill();
1873
- resolve2(pid);
2158
+ resolve4(pid);
1874
2159
  return;
1875
2160
  }
1876
2161
  }
@@ -1891,7 +2176,7 @@ function listRunningProcesses(config, options = {}) {
1891
2176
  if (options.targetProcessName) {
1892
2177
  reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));
1893
2178
  } else {
1894
- resolve2(processes);
2179
+ resolve4(processes);
1895
2180
  }
1896
2181
  }, timeoutMs);
1897
2182
  proc.on("close", () => {
@@ -1901,7 +2186,7 @@ function listRunningProcesses(config, options = {}) {
1901
2186
  if (options.targetProcessName) {
1902
2187
  reject(new OniroError(`Could not find process for bundle: ${options.targetProcessName}`));
1903
2188
  } else {
1904
- resolve2(processes);
2189
+ resolve4(processes);
1905
2190
  }
1906
2191
  });
1907
2192
  });
@@ -1921,8 +2206,17 @@ async function findRunningProcess(opts) {
1921
2206
  logger: opts.logger
1922
2207
  });
1923
2208
  const pid = res.stdout.trim().split(/\s+/).filter(Boolean)[0];
1924
- if (res.code !== 0 || !pid || !/^\d+$/.test(pid)) return null;
1925
- return { pid, name: opts.bundle };
2209
+ if (res.code === 0 && pid && /^\d+$/.test(pid)) return { pid, name: opts.bundle };
2210
+ try {
2211
+ const list = await listRunningProcesses(opts.config, { timeoutMs: 1200, logger: opts.logger });
2212
+ if (Array.isArray(list)) {
2213
+ const mine = (name) => name === opts.bundle || name.startsWith(`${opts.bundle}/`) || name.startsWith(`${opts.bundle}:`);
2214
+ const match = list.find((p) => p.name === opts.bundle) ?? list.find((p) => mine(p.name));
2215
+ if (match) return match;
2216
+ }
2217
+ } catch {
2218
+ }
2219
+ return null;
1926
2220
  }
1927
2221
  async function uninstallApp(opts) {
1928
2222
  const logger = scopedLogger(opts.logger ?? noopLogger, "hdc");
@@ -2036,12 +2330,12 @@ async function reboot(opts) {
2036
2330
  }
2037
2331
 
2038
2332
  // src/hdc/screen.ts
2039
- var fs16 = __toESM(require("fs"), 1);
2040
- var os9 = __toESM(require("os"), 1);
2041
- var path15 = __toESM(require("path"), 1);
2333
+ var fs17 = __toESM(require("fs"), 1);
2334
+ var os8 = __toESM(require("os"), 1);
2335
+ var path17 = __toESM(require("path"), 1);
2042
2336
  var import_node_crypto = require("crypto");
2043
2337
  function tmpName(ext) {
2044
- return path15.join(os9.tmpdir(), `oniro_screen_${(0, import_node_crypto.randomBytes)(6).toString("hex")}.${ext}`);
2338
+ return path17.join(os8.tmpdir(), `oniro_screen_${(0, import_node_crypto.randomBytes)(6).toString("hex")}.${ext}`);
2045
2339
  }
2046
2340
  async function takeScreenshot(opts) {
2047
2341
  const remote = "/data/local/tmp/oniro_screenshot.jpeg";
@@ -2051,11 +2345,11 @@ async function takeScreenshot(opts) {
2051
2345
  const local = tmpName("jpeg");
2052
2346
  try {
2053
2347
  await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });
2054
- const pixels = await fs16.promises.readFile(local);
2348
+ const pixels = await fs17.promises.readFile(local);
2055
2349
  const size = await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial }) ?? { width: 0, height: 0 };
2056
2350
  return { pixels, width: size.width, height: size.height };
2057
2351
  } finally {
2058
- fs16.promises.unlink(local).catch(() => {
2352
+ fs17.promises.unlink(local).catch(() => {
2059
2353
  });
2060
2354
  void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {
2061
2355
  });
@@ -2074,9 +2368,9 @@ async function captureBurst(opts) {
2074
2368
  const local = tmpName(`burst_${i}.jpeg`);
2075
2369
  try {
2076
2370
  await recvFile({ config: opts.config, remote: `${remoteDir}/f${i}.jpeg`, local, deviceSerial: opts.deviceSerial });
2077
- frames.push(await fs16.promises.readFile(local));
2371
+ frames.push(await fs17.promises.readFile(local));
2078
2372
  } finally {
2079
- fs16.promises.unlink(local).catch(() => {
2373
+ fs17.promises.unlink(local).catch(() => {
2080
2374
  });
2081
2375
  }
2082
2376
  }
@@ -2120,8 +2414,8 @@ function buildInputCommand(opts) {
2120
2414
  }
2121
2415
  async function sendInput(opts) {
2122
2416
  const cmd = buildInputCommand(opts);
2123
- const res = await shell({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2124
- ensureOk(res, `hdc shell ${cmd}`);
2417
+ const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2418
+ ensureRemoteOk(res, `hdc shell ${cmd}`);
2125
2419
  }
2126
2420
  function buildGestureCommands(waypoints) {
2127
2421
  if (waypoints.length < 2) {
@@ -2164,32 +2458,47 @@ function waypointsToRawEvents(waypoints, holdStartMs = 0, holdEndMs = 0) {
2164
2458
  events.push({ type: "up", x: last.x, y: last.y, t: last.t + holdStartMs + holdEndMs });
2165
2459
  return events;
2166
2460
  }
2461
+ var UITEST_VELOCITY_MIN = 200;
2462
+ var UITEST_VELOCITY_MAX = 4e4;
2463
+ function buildGestureUitestCommand(waypoints, opts = {}) {
2464
+ if (waypoints.length < 2) throw new OniroError("sendGesture requires at least two waypoints.");
2465
+ const a = waypoints[0];
2466
+ const b = waypoints[waypoints.length - 1];
2467
+ const dist = Math.hypot(b.x - a.x, b.y - a.y);
2468
+ const dtMs = b.t - a.t;
2469
+ const op = (opts.holdStartMs ?? 0) > 0 ? "drag" : "swipe";
2470
+ let cmd = `uitest uiInput ${op} ${a.x} ${a.y} ${b.x} ${b.y}`;
2471
+ if (dtMs > 0 && dist > 0) {
2472
+ const v = Math.round(dist / (dtMs / 1e3));
2473
+ cmd += ` ${Math.max(UITEST_VELOCITY_MIN, Math.min(UITEST_VELOCITY_MAX, v))}`;
2474
+ }
2475
+ return cmd;
2476
+ }
2167
2477
  async function sendGesture(opts) {
2168
- const wantsHold = (opts.holdStartMs ?? 0) > 0 || (opts.holdEndMs ?? 0) > 0;
2169
- if (wantsHold) {
2170
- await sendRawTouch({
2171
- config: opts.config,
2172
- events: waypointsToRawEvents(opts.waypoints, opts.holdStartMs, opts.holdEndMs),
2173
- deviceSerial: opts.deviceSerial,
2174
- logger: opts.logger
2175
- });
2176
- return;
2478
+ if ((opts.holdEndMs ?? 0) > 0) {
2479
+ opts.logger?.warn(
2480
+ "sendGesture: hold-end has no uitest equivalent and is ignored; use sendRawTouch for a trailing hold."
2481
+ );
2177
2482
  }
2178
- for (const cmd of buildGestureCommands(opts.waypoints)) {
2179
- const res = await shell({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2180
- ensureOk(res, `hdc shell ${cmd}`);
2483
+ if (opts.waypoints.length > 2) {
2484
+ opts.logger?.debug(
2485
+ `sendGesture: ${opts.waypoints.length} waypoints collapsed to first\u2192last (uitest has no polyline path).`
2486
+ );
2181
2487
  }
2488
+ const cmd = buildGestureUitestCommand(opts.waypoints, { holdStartMs: opts.holdStartMs });
2489
+ const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2490
+ ensureRemoteOk(res, `hdc shell ${cmd}`);
2182
2491
  }
2183
2492
  async function sendRawTouch(opts) {
2184
2493
  const cmd = buildRawTouchCommand(opts.events);
2185
- const res = await shell({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2186
- ensureOk(res, `hdc shell ${cmd}`);
2494
+ const res = await shellChecked({ config: opts.config, command: cmd, deviceSerial: opts.deviceSerial, timeoutMs: 3e4, logger: opts.logger });
2495
+ ensureRemoteOk(res, `hdc shell ${cmd}`);
2187
2496
  }
2188
2497
 
2189
2498
  // src/hdc/dump.ts
2190
- var fs17 = __toESM(require("fs"), 1);
2191
- var os10 = __toESM(require("os"), 1);
2192
- var path16 = __toESM(require("path"), 1);
2499
+ var fs18 = __toESM(require("fs"), 1);
2500
+ var os9 = __toESM(require("os"), 1);
2501
+ var path18 = __toESM(require("path"), 1);
2193
2502
  var import_node_crypto2 = require("crypto");
2194
2503
  function parseBounds(s) {
2195
2504
  const m = /^\[(-?\d+),(-?\d+)\]\[(-?\d+),(-?\d+)\]$/.exec(s ?? "");
@@ -2274,10 +2583,10 @@ async function dumpLayout(opts) {
2274
2583
  if (!m) throw new OniroError(`Could not parse dumpLayout output:
2275
2584
  ${dump.stdout}`);
2276
2585
  const remote = m[1];
2277
- const local = path16.join(os10.tmpdir(), `oniro_layout_${(0, import_node_crypto2.randomBytes)(6).toString("hex")}.json`);
2586
+ const local = path18.join(os9.tmpdir(), `oniro_layout_${(0, import_node_crypto2.randomBytes)(6).toString("hex")}.json`);
2278
2587
  try {
2279
2588
  await recvFile({ config: opts.config, remote, local, deviceSerial: opts.deviceSerial, timeoutMs });
2280
- const parsed = JSON.parse(await fs17.promises.readFile(local, "utf8"));
2589
+ const parsed = JSON.parse(await fs18.promises.readFile(local, "utf8"));
2281
2590
  const display = await getDisplaySize(opts.config, { deviceSerial: opts.deviceSerial });
2282
2591
  if (opts.prune === false) {
2283
2592
  return { display, tree: parsed };
@@ -2286,7 +2595,7 @@ ${dump.stdout}`);
2286
2595
  const tree = Array.isArray(prunedRaw) ? { children: prunedRaw } : prunedRaw ?? { children: [] };
2287
2596
  return { display, tree };
2288
2597
  } finally {
2289
- fs17.promises.unlink(local).catch(() => {
2598
+ fs18.promises.unlink(local).catch(() => {
2290
2599
  });
2291
2600
  void shell({ config: opts.config, command: `rm -f ${remote}`, deviceSerial: opts.deviceSerial }).catch(() => {
2292
2601
  });
@@ -2298,7 +2607,7 @@ var import_node_child_process6 = require("child_process");
2298
2607
  function setHilogLevel(opts) {
2299
2608
  const logger = opts.logger ?? noopLogger;
2300
2609
  const hdc = getHdcPath(opts.config);
2301
- return new Promise((resolve2, reject) => {
2610
+ return new Promise((resolve4, reject) => {
2302
2611
  const child = (0, import_node_child_process6.spawn)(hdc, ["shell", "hilog", "-b", opts.level]);
2303
2612
  let stderr = "";
2304
2613
  child.stderr.on("data", (chunk) => {
@@ -2310,7 +2619,7 @@ function setHilogLevel(opts) {
2310
2619
  });
2311
2620
  child.once("close", (code) => {
2312
2621
  if (code === 0) {
2313
- resolve2();
2622
+ resolve4();
2314
2623
  } else {
2315
2624
  const msg = stderr.trim() || `hdc shell hilog -b ${opts.level} exited with code ${code}`;
2316
2625
  logger.error(`[hilog] ${msg}`);
@@ -2365,7 +2674,7 @@ async function resolveProcessId(config, bundle, deviceSerial) {
2365
2674
  return proc?.pid;
2366
2675
  }
2367
2676
  function waitForLog(opts) {
2368
- return new Promise((resolve2, reject) => {
2677
+ return new Promise((resolve4, reject) => {
2369
2678
  const deadline = Date.now() + opts.timeoutMs;
2370
2679
  let settled = false;
2371
2680
  let child = null;
@@ -2387,7 +2696,7 @@ function waitForLog(opts) {
2387
2696
  if (settled) return;
2388
2697
  settled = true;
2389
2698
  cleanup();
2390
- resolve2(entry);
2699
+ resolve4(entry);
2391
2700
  };
2392
2701
  const fail = (err) => {
2393
2702
  if (settled) return;
@@ -2434,7 +2743,7 @@ function waitForLog(opts) {
2434
2743
  });
2435
2744
  }
2436
2745
  function watchLog(opts) {
2437
- return new Promise((resolve2, reject) => {
2746
+ return new Promise((resolve4, reject) => {
2438
2747
  const matches = [];
2439
2748
  let settled = false;
2440
2749
  let child = null;
@@ -2454,7 +2763,7 @@ function watchLog(opts) {
2454
2763
  if (settled) return;
2455
2764
  settled = true;
2456
2765
  cleanup();
2457
- resolve2(opts.dedup === false ? matches : dedupEntries(matches));
2766
+ resolve4(opts.dedup === false ? matches : dedupEntries(matches));
2458
2767
  };
2459
2768
  const onAbort = () => {
2460
2769
  if (settled) return;
@@ -2506,8 +2815,8 @@ async function dumpLog(opts) {
2506
2815
  }
2507
2816
 
2508
2817
  // src/build/runHvigorw.ts
2509
- var fs18 = __toESM(require("fs"), 1);
2510
- var path17 = __toESM(require("path"), 1);
2818
+ var fs19 = __toESM(require("fs"), 1);
2819
+ var path19 = __toESM(require("path"), 1);
2511
2820
  var import_node_child_process7 = require("child_process");
2512
2821
  function buildHvigorwArgs(opts) {
2513
2822
  const args = [opts.task ?? "assembleHap", "--mode", "module"];
@@ -2522,17 +2831,17 @@ function buildHvigorwArgs(opts) {
2522
2831
  function runHvigorw(opts) {
2523
2832
  const { config, projectDir } = opts;
2524
2833
  const logger = opts.logger ?? noopLogger;
2525
- if (!fs18.existsSync(path17.join(projectDir, "build-profile.json5"))) {
2834
+ if (!fs19.existsSync(path19.join(projectDir, "build-profile.json5"))) {
2526
2835
  throw new OniroError(`Not an OpenHarmony project: ${projectDir} (build-profile.json5 not found).`);
2527
2836
  }
2528
- if (!fs18.existsSync(getCmdToolsPath(config))) {
2837
+ if (!fs19.existsSync(getCmdToolsPath(config))) {
2529
2838
  throw new CmdToolsNotInstalledError(getCmdToolsPath(config));
2530
2839
  }
2531
2840
  const hvigorw = getHvigorwPath(config, projectDir);
2532
2841
  const args = buildHvigorwArgs(opts);
2533
2842
  if (process.platform !== "win32") {
2534
2843
  try {
2535
- fs18.chmodSync(hvigorw, 493);
2844
+ fs19.chmodSync(hvigorw, 493);
2536
2845
  } catch {
2537
2846
  }
2538
2847
  }
@@ -2540,7 +2849,7 @@ function runHvigorw(opts) {
2540
2849
  ...process.env,
2541
2850
  OHOS_BASE_SDK_HOME: getOhosBaseSdkHome(config)
2542
2851
  };
2543
- return new Promise((resolve2, reject) => {
2852
+ return new Promise((resolve4, reject) => {
2544
2853
  if (opts.abortSignal?.aborted) {
2545
2854
  reject(new CancelledError("hvigorw build cancelled."));
2546
2855
  return;
@@ -2581,19 +2890,18 @@ function runHvigorw(opts) {
2581
2890
  settled = true;
2582
2891
  cleanup();
2583
2892
  const exitCode = code ?? 1;
2584
- if (exitCode === 0) resolve2({ exitCode });
2893
+ if (exitCode === 0) resolve4({ exitCode });
2585
2894
  else reject(new OniroError(`hvigorw exited with code ${exitCode}`));
2586
2895
  });
2587
2896
  });
2588
2897
  }
2589
2898
 
2590
2899
  // src/build/discoverHaps.ts
2591
- var fs19 = __toESM(require("fs"), 1);
2592
- var path18 = __toESM(require("path"), 1);
2593
- function moduleOf(projectDir, hapPath) {
2594
- const rel = path18.relative(projectDir, hapPath);
2595
- const first = rel.split(path18.sep)[0];
2596
- return first && first !== ".." ? first : "(root)";
2900
+ var fs20 = __toESM(require("fs"), 1);
2901
+ var path20 = __toESM(require("path"), 1);
2902
+ function moduleOfHap(hapFileName) {
2903
+ const dash = hapFileName.indexOf("-");
2904
+ return dash > 0 ? hapFileName.slice(0, dash) : hapFileName.replace(/\.hap$/i, "");
2597
2905
  }
2598
2906
  async function discoverHaps(opts) {
2599
2907
  const { projectDir } = opts;
@@ -2601,14 +2909,14 @@ async function discoverHaps(opts) {
2601
2909
  const result = {};
2602
2910
  const walk = async (dir, depth) => {
2603
2911
  if (depth > maxDepth) return;
2604
- const entries = await fs19.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
2912
+ const entries = await fs20.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
2605
2913
  for (const e of entries) {
2606
- const full = path18.join(dir, e.name);
2914
+ const full = path20.join(dir, e.name);
2607
2915
  if (e.isDirectory()) {
2608
2916
  if (e.name === "node_modules" || e.name === "oh_modules" || e.name === ".git") continue;
2609
2917
  await walk(full, depth + 1);
2610
2918
  } else if (e.isFile() && e.name.endsWith(".hap")) {
2611
- const moduleName = moduleOf(projectDir, full);
2919
+ const moduleName = moduleOfHap(e.name);
2612
2920
  const bucket = result[moduleName] ??= { signed: [], unsigned: [] };
2613
2921
  if (e.name.includes("unsigned")) bucket.unsigned.push(full);
2614
2922
  else if (e.name.includes("signed")) bucket.signed.push(full);
@@ -2620,8 +2928,8 @@ async function discoverHaps(opts) {
2620
2928
  }
2621
2929
 
2622
2930
  // src/build/ohpm.ts
2623
- var fs20 = __toESM(require("fs"), 1);
2624
- var path19 = __toESM(require("path"), 1);
2931
+ var fs21 = __toESM(require("fs"), 1);
2932
+ var path21 = __toESM(require("path"), 1);
2625
2933
  function runOhpm(opts) {
2626
2934
  return runProcess({
2627
2935
  command: getOhpmPath(opts.config),
@@ -2634,7 +2942,7 @@ function runOhpm(opts) {
2634
2942
  });
2635
2943
  }
2636
2944
  async function ensureOhModules(opts) {
2637
- if (fs20.existsSync(path19.join(opts.projectDir, "oh_modules"))) {
2945
+ if (fs21.existsSync(path21.join(opts.projectDir, "oh_modules"))) {
2638
2946
  return { installed: false };
2639
2947
  }
2640
2948
  const res = await runOhpm({
@@ -2729,21 +3037,21 @@ function isValidBundleName(bundleName) {
2729
3037
  }
2730
3038
 
2731
3039
  // src/project/templates.ts
2732
- var fs21 = __toESM(require("fs"), 1);
2733
- var path20 = __toESM(require("path"), 1);
3040
+ var fs22 = __toESM(require("fs"), 1);
3041
+ var path22 = __toESM(require("path"), 1);
2734
3042
  function toHumanTemplateName(folderName) {
2735
3043
  return folderName.replace(/([a-z])([A-Z])/g, "$1 $2");
2736
3044
  }
2737
3045
  function listTemplates(templateRoot) {
2738
- if (!fs21.existsSync(templateRoot)) return [];
2739
- const entries = fs21.readdirSync(templateRoot, { withFileTypes: true });
3046
+ if (!fs22.existsSync(templateRoot)) return [];
3047
+ const entries = fs22.readdirSync(templateRoot, { withFileTypes: true });
2740
3048
  return entries.filter((e) => e.isDirectory()).map((e) => {
2741
- const dir = path20.join(templateRoot, e.name);
2742
- const metaPath = path20.join(dir, "template.json");
3049
+ const dir = path22.join(templateRoot, e.name);
3050
+ const metaPath = path22.join(dir, "template.json");
2743
3051
  let meta = {};
2744
- if (fs21.existsSync(metaPath)) {
3052
+ if (fs22.existsSync(metaPath)) {
2745
3053
  try {
2746
- meta = JSON.parse(fs21.readFileSync(metaPath, "utf8"));
3054
+ meta = JSON.parse(fs22.readFileSync(metaPath, "utf8"));
2747
3055
  } catch {
2748
3056
  }
2749
3057
  }
@@ -2758,57 +3066,57 @@ function listTemplates(templateRoot) {
2758
3066
  function validateTemplateLayout(templateDir, defaultModuleName) {
2759
3067
  const required = [
2760
3068
  "build-profile.json5",
2761
- path20.join("AppScope", "app.json5"),
2762
- path20.join(defaultModuleName, "src", "main", "module.json5"),
2763
- path20.join(defaultModuleName, "oh-package.json5"),
3069
+ path22.join("AppScope", "app.json5"),
3070
+ path22.join(defaultModuleName, "src", "main", "module.json5"),
3071
+ path22.join(defaultModuleName, "oh-package.json5"),
2764
3072
  "hvigorfile.ts"
2765
3073
  ];
2766
- return required.filter((rel) => !fs21.existsSync(path20.join(templateDir, rel)));
3074
+ return required.filter((rel) => !fs22.existsSync(path22.join(templateDir, rel)));
2767
3075
  }
2768
3076
 
2769
3077
  // src/project/createScaffold.ts
2770
- var fs23 = __toESM(require("fs"), 1);
2771
- var path21 = __toESM(require("path"), 1);
3078
+ var fs24 = __toESM(require("fs"), 1);
3079
+ var path23 = __toESM(require("path"), 1);
2772
3080
 
2773
3081
  // src/project/jsonHelpers.ts
2774
- var fs22 = __toESM(require("fs"), 1);
3082
+ var fs23 = __toESM(require("fs"), 1);
2775
3083
  var import_json54 = __toESM(require("json5"), 1);
2776
3084
  function readJson5File(filePath) {
2777
- return import_json54.default.parse(fs22.readFileSync(filePath, "utf8"));
3085
+ return import_json54.default.parse(fs23.readFileSync(filePath, "utf8"));
2778
3086
  }
2779
3087
  function writeJson5File(filePath, value) {
2780
- fs22.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
3088
+ fs23.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
2781
3089
  }
2782
3090
  function readJsonFile(filePath) {
2783
- return JSON.parse(fs22.readFileSync(filePath, "utf8"));
3091
+ return JSON.parse(fs23.readFileSync(filePath, "utf8"));
2784
3092
  }
2785
3093
  function writeJsonFile(filePath, value) {
2786
- fs22.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
3094
+ fs23.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
2787
3095
  }
2788
3096
 
2789
3097
  // src/project/createScaffold.ts
2790
3098
  var IGNORED_DIRS = /* @__PURE__ */ new Set(["oh_modules", "node_modules", "build", ".hvigor"]);
2791
3099
  async function pathExists(p) {
2792
3100
  try {
2793
- await fs23.promises.access(p);
3101
+ await fs24.promises.access(p);
2794
3102
  return true;
2795
3103
  } catch {
2796
3104
  return false;
2797
3105
  }
2798
3106
  }
2799
3107
  async function copyDirRecursive(srcDir, destDir) {
2800
- await fs23.promises.mkdir(destDir, { recursive: true });
2801
- const entries = await fs23.promises.readdir(srcDir, { withFileTypes: true });
3108
+ await fs24.promises.mkdir(destDir, { recursive: true });
3109
+ const entries = await fs24.promises.readdir(srcDir, { withFileTypes: true });
2802
3110
  for (const entry of entries) {
2803
- const src = path21.join(srcDir, entry.name);
2804
- const dest = path21.join(destDir, entry.name);
3111
+ const src = path23.join(srcDir, entry.name);
3112
+ const dest = path23.join(destDir, entry.name);
2805
3113
  if (entry.isDirectory()) {
2806
3114
  await copyDirRecursive(src, dest);
2807
3115
  } else if (entry.isSymbolicLink()) {
2808
3116
  continue;
2809
3117
  } else if (entry.isFile()) {
2810
3118
  if (entry.name === "template.json") continue;
2811
- await fs23.promises.copyFile(src, dest);
3119
+ await fs24.promises.copyFile(src, dest);
2812
3120
  }
2813
3121
  }
2814
3122
  }
@@ -2816,9 +3124,9 @@ async function normalizeJson5ToJson(projectDir, logger) {
2816
3124
  const stack = [projectDir];
2817
3125
  while (stack.length > 0) {
2818
3126
  const currentDir = stack.pop();
2819
- const entries = await fs23.promises.readdir(currentDir, { withFileTypes: true });
3127
+ const entries = await fs24.promises.readdir(currentDir, { withFileTypes: true });
2820
3128
  for (const entry of entries) {
2821
- const fullPath = path21.join(currentDir, entry.name);
3129
+ const fullPath = path23.join(currentDir, entry.name);
2822
3130
  if (entry.isDirectory()) {
2823
3131
  if (IGNORED_DIRS.has(entry.name)) continue;
2824
3132
  stack.push(fullPath);
@@ -2840,23 +3148,23 @@ function toJavaPropertiesPath(p) {
2840
3148
  function createOrUpdateLocalProperties(projectDir, sdkDir) {
2841
3149
  const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}
2842
3150
  `;
2843
- fs23.writeFileSync(path21.join(projectDir, "local.properties"), content, "utf8");
3151
+ fs24.writeFileSync(path23.join(projectDir, "local.properties"), content, "utf8");
2844
3152
  }
2845
3153
  function renameIfExists(fromPath, toPath) {
2846
- if (fs23.existsSync(fromPath) && fromPath !== toPath) {
2847
- fs23.renameSync(fromPath, toPath);
3154
+ if (fs24.existsSync(fromPath) && fromPath !== toPath) {
3155
+ fs24.renameSync(fromPath, toPath);
2848
3156
  }
2849
3157
  }
2850
3158
  function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
2851
- const appJsonPath = path21.join(projectDir, "AppScope", "app.json5");
2852
- if (fs23.existsSync(appJsonPath)) {
3159
+ const appJsonPath = path23.join(projectDir, "AppScope", "app.json5");
3160
+ if (fs24.existsSync(appJsonPath)) {
2853
3161
  const appJson = readJson5File(appJsonPath);
2854
3162
  appJson.app = appJson.app ?? {};
2855
3163
  appJson.app.bundleName = args.bundleName;
2856
3164
  writeJson5File(appJsonPath, appJson);
2857
3165
  }
2858
- const stringsPath = path21.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
2859
- if (fs23.existsSync(stringsPath)) {
3166
+ const stringsPath = path23.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
3167
+ if (fs24.existsSync(stringsPath)) {
2860
3168
  const strings = readJsonFile(stringsPath);
2861
3169
  if (Array.isArray(strings.string)) {
2862
3170
  const appName = strings.string.find((s) => s.name === "app_name");
@@ -2864,8 +3172,8 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
2864
3172
  }
2865
3173
  writeJsonFile(stringsPath, strings);
2866
3174
  }
2867
- const buildProfilePath = path21.join(projectDir, "build-profile.json5");
2868
- if (fs23.existsSync(buildProfilePath)) {
3175
+ const buildProfilePath = path23.join(projectDir, "build-profile.json5");
3176
+ if (fs24.existsSync(buildProfilePath)) {
2869
3177
  const buildProfile = readJson5File(buildProfilePath);
2870
3178
  buildProfile.app = buildProfile.app ?? {};
2871
3179
  if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {
@@ -2878,23 +3186,23 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
2878
3186
  }
2879
3187
  writeJson5File(buildProfilePath, buildProfile);
2880
3188
  }
2881
- const moduleJsonPath = path21.join(projectDir, args.moduleName, "src", "main", "module.json5");
2882
- if (fs23.existsSync(moduleJsonPath)) {
3189
+ const moduleJsonPath = path23.join(projectDir, args.moduleName, "src", "main", "module.json5");
3190
+ if (fs24.existsSync(moduleJsonPath)) {
2883
3191
  const moduleJson = readJson5File(moduleJsonPath);
2884
3192
  moduleJson.module = moduleJson.module ?? {};
2885
3193
  moduleJson.module.name = args.moduleName;
2886
3194
  writeJson5File(moduleJsonPath, moduleJson);
2887
3195
  }
2888
- const moduleOhPackagePath = path21.join(projectDir, args.moduleName, "oh-package.json5");
2889
- if (fs23.existsSync(moduleOhPackagePath)) {
3196
+ const moduleOhPackagePath = path23.join(projectDir, args.moduleName, "oh-package.json5");
3197
+ if (fs24.existsSync(moduleOhPackagePath)) {
2890
3198
  const pkg = readJson5File(moduleOhPackagePath);
2891
3199
  pkg.name = args.moduleName;
2892
3200
  writeJson5File(moduleOhPackagePath, pkg);
2893
3201
  }
2894
- const vscodeDir = path21.join(projectDir, ".vscode");
2895
- fs23.mkdirSync(vscodeDir, { recursive: true });
3202
+ const vscodeDir = path23.join(projectDir, ".vscode");
3203
+ fs24.mkdirSync(vscodeDir, { recursive: true });
2896
3204
  const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;
2897
- writeJsonFile(path21.join(vscodeDir, "settings.json"), {
3205
+ writeJsonFile(path23.join(vscodeDir, "settings.json"), {
2898
3206
  "oniro.hapPath": hapPath,
2899
3207
  "files.associations": { "*.json5": "jsonc" }
2900
3208
  });
@@ -2911,7 +3219,7 @@ async function createScaffold(opts) {
2911
3219
  if (!opts.location || !await pathExists(opts.location)) {
2912
3220
  throw new OniroError(`Location does not exist: ${opts.location}`);
2913
3221
  }
2914
- const templateDir = path21.join(opts.templateRoot, opts.templateId);
3222
+ const templateDir = path23.join(opts.templateRoot, opts.templateId);
2915
3223
  if (!await pathExists(templateDir)) {
2916
3224
  throw new OniroError(`Template not found: ${templateDir}`);
2917
3225
  }
@@ -2924,17 +3232,17 @@ async function createScaffold(opts) {
2924
3232
  throw new OniroError(`Template '${opts.templateId}' is missing required files:
2925
3233
  - ${missing.join("\n- ")}`);
2926
3234
  }
2927
- const projectDir = path21.join(opts.location, opts.projectName);
3235
+ const projectDir = path23.join(opts.location, opts.projectName);
2928
3236
  if (await pathExists(projectDir)) {
2929
3237
  if (!opts.overwrite) {
2930
3238
  throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);
2931
3239
  }
2932
- await fs23.promises.rm(projectDir, { recursive: true, force: true });
3240
+ await fs24.promises.rm(projectDir, { recursive: true, force: true });
2933
3241
  }
2934
3242
  logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);
2935
3243
  await copyDirRecursive(templateDir, projectDir);
2936
3244
  if (moduleName !== defaultModuleName) {
2937
- renameIfExists(path21.join(projectDir, defaultModuleName), path21.join(projectDir, moduleName));
3245
+ renameIfExists(path23.join(projectDir, defaultModuleName), path23.join(projectDir, moduleName));
2938
3246
  }
2939
3247
  updateTemplateConfigs(
2940
3248
  projectDir,
@@ -2951,11 +3259,11 @@ async function createScaffold(opts) {
2951
3259
  }
2952
3260
 
2953
3261
  // src/project/listModules.ts
2954
- var fs24 = __toESM(require("fs"), 1);
2955
- var path22 = __toESM(require("path"), 1);
3262
+ var fs25 = __toESM(require("fs"), 1);
3263
+ var path24 = __toESM(require("path"), 1);
2956
3264
  function listModules(opts) {
2957
- const buildProfile = path22.join(opts.projectDir, "build-profile.json5");
2958
- if (!fs24.existsSync(buildProfile)) {
3265
+ const buildProfile = path24.join(opts.projectDir, "build-profile.json5");
3266
+ if (!fs25.existsSync(buildProfile)) {
2959
3267
  throw new OniroError(`build-profile.json5 not found at ${buildProfile}`);
2960
3268
  }
2961
3269
  const parsed = readJson5File(buildProfile);
@@ -2967,12 +3275,12 @@ function listModules(opts) {
2967
3275
  }
2968
3276
 
2969
3277
  // src/project/abilities.ts
2970
- var fs25 = __toESM(require("fs"), 1);
2971
- var path23 = __toESM(require("path"), 1);
3278
+ var fs26 = __toESM(require("fs"), 1);
3279
+ var path25 = __toESM(require("path"), 1);
2972
3280
  function listAbilities(opts) {
2973
3281
  const moduleName = opts.moduleName ?? "entry";
2974
- const moduleJsonPath = path23.join(opts.projectDir, moduleName, "src", "main", "module.json5");
2975
- if (!fs25.existsSync(moduleJsonPath)) {
3282
+ const moduleJsonPath = path25.join(opts.projectDir, moduleName, "src", "main", "module.json5");
3283
+ if (!fs26.existsSync(moduleJsonPath)) {
2976
3284
  throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
2977
3285
  }
2978
3286
  const parsed = readJson5File(moduleJsonPath);
@@ -2980,12 +3288,12 @@ function listAbilities(opts) {
2980
3288
  }
2981
3289
 
2982
3290
  // src/project/prepareSigning.ts
2983
- var fs26 = __toESM(require("fs"), 1);
2984
- var path24 = __toESM(require("path"), 1);
3291
+ var fs27 = __toESM(require("fs"), 1);
3292
+ var path26 = __toESM(require("path"), 1);
2985
3293
  function hasSigningArtifacts(dir) {
2986
- if (!fs26.existsSync(path24.join(dir, "signatures"))) return false;
2987
- const buildProfile = path24.join(dir, "build-profile.json5");
2988
- if (!fs26.existsSync(buildProfile)) return false;
3294
+ if (!fs27.existsSync(path26.join(dir, "signatures"))) return false;
3295
+ const buildProfile = path26.join(dir, "build-profile.json5");
3296
+ if (!fs27.existsSync(buildProfile)) return false;
2989
3297
  try {
2990
3298
  const parsed = readJson5File(buildProfile);
2991
3299
  return Array.isArray(parsed.app?.signingConfigs) && parsed.app.signingConfigs.length > 0;
@@ -3075,8 +3383,8 @@ async function diffHapAssets(opts) {
3075
3383
  }
3076
3384
 
3077
3385
  // src/install/apply.ts
3078
- var fs27 = __toESM(require("fs"), 1);
3079
- var path25 = __toESM(require("path"), 1);
3386
+ var fs28 = __toESM(require("fs"), 1);
3387
+ var path27 = __toESM(require("path"), 1);
3080
3388
  function decideInstallMethod(s) {
3081
3389
  if (!s.signInfoInconsistent) return "replace";
3082
3390
  if (s.isSystemBundle && !s.allowUninstall) return "refuse";
@@ -3097,7 +3405,7 @@ async function pidOf(config, bundle, deviceSerial) {
3097
3405
  async function resolveHapPath(opts) {
3098
3406
  let hapPath = opts.hapPath;
3099
3407
  if (hapPath) {
3100
- if (!path25.isAbsolute(hapPath) && opts.projectDir) hapPath = path25.join(opts.projectDir, hapPath);
3408
+ if (!path27.isAbsolute(hapPath) && opts.projectDir) hapPath = path27.join(opts.projectDir, hapPath);
3101
3409
  } else {
3102
3410
  if (!opts.projectDir) throw new OniroError("applyChanges requires hapPath or projectDir.");
3103
3411
  const haps = await discoverHaps({ projectDir: opts.projectDir });
@@ -3116,7 +3424,7 @@ async function resolveHapPath(opts) {
3116
3424
  hapPath = withSigned[0][1].signed[0];
3117
3425
  }
3118
3426
  }
3119
- if (!fs27.existsSync(hapPath)) throw new OniroError(`HAP not found at ${hapPath}.`);
3427
+ if (!fs28.existsSync(hapPath)) throw new OniroError(`HAP not found at ${hapPath}.`);
3120
3428
  return hapPath;
3121
3429
  }
3122
3430
  async function applyChanges(opts) {
@@ -3126,7 +3434,7 @@ async function applyChanges(opts) {
3126
3434
  const allowUninstall = opts.allowUninstall ?? false;
3127
3435
  const hapPath = await resolveHapPath(opts);
3128
3436
  let assetsChanged = false;
3129
- if (opts.installedHapPath && fs27.existsSync(opts.installedHapPath)) {
3437
+ if (opts.installedHapPath && fs28.existsSync(opts.installedHapPath)) {
3130
3438
  try {
3131
3439
  const diff = await diffHapAssets({ installedHap: opts.installedHapPath, newHap: hapPath });
3132
3440
  assetsChanged = diff.addedAssetPaths.length > 0 || diff.removedAssetPaths.length > 0;
@@ -3168,7 +3476,7 @@ async function applyChanges(opts) {
3168
3476
  }
3169
3477
 
3170
3478
  // src/index.ts
3171
- var VERSION = "0.7.0";
3479
+ var VERSION = "0.8.0";
3172
3480
  // Annotate the CommonJS export names for ESM import in node:
3173
3481
  0 && (module.exports = {
3174
3482
  ALL_SDKS,
@@ -3178,22 +3486,28 @@ var VERSION = "0.7.0";
3178
3486
  ChecksumMismatchError,
3179
3487
  CmdToolsNotInstalledError,
3180
3488
  CommandFailedError,
3489
+ INSTALL_TMP_DIRNAME,
3490
+ InsufficientSpaceError,
3181
3491
  OHOS_URL_BASE,
3182
3492
  OniroError,
3183
3493
  SdkNotInstalledError,
3494
+ TMP_DIR_HINT,
3184
3495
  UnsupportedPlatformError,
3185
3496
  VERSION,
3186
3497
  applyChanges,
3187
3498
  attemptHdcConnection,
3188
3499
  buildGestureCommands,
3500
+ buildGestureUitestCommand,
3189
3501
  buildHap,
3190
3502
  buildHvigorwArgs,
3191
3503
  buildInputCommand,
3192
3504
  buildRawTouchCommand,
3193
3505
  captureBurst,
3194
3506
  consoleLogger,
3507
+ createInstallTempDir,
3195
3508
  createMaterial,
3196
3509
  createScaffold,
3510
+ createTempWorkDir,
3197
3511
  decideInstallMethod,
3198
3512
  decideReboot,
3199
3513
  decryptPwd,
@@ -3214,14 +3528,17 @@ var VERSION = "0.7.0";
3214
3528
  dumpScreen,
3215
3529
  dumpWindow,
3216
3530
  encryptPwd,
3531
+ ensureFreeSpace,
3217
3532
  ensureOhModules,
3218
3533
  ensureOk,
3534
+ ensureRemoteOk,
3219
3535
  extractTarball,
3220
3536
  extractZipWithProgress,
3221
3537
  findAppProcessId,
3222
3538
  findCmdToolsSourceDir,
3223
3539
  findRunningProcess,
3224
3540
  forceStop,
3541
+ formatBytes,
3225
3542
  generateSigningConfigs,
3226
3543
  getBundleName,
3227
3544
  getCmdToolsBin,
@@ -3231,6 +3548,7 @@ var VERSION = "0.7.0";
3231
3548
  getDeviceInfo,
3232
3549
  getDisplaySize,
3233
3550
  getEmulatorDir,
3551
+ getFreeSpaceBytes,
3234
3552
  getHdcPath,
3235
3553
  getHvigorwPath,
3236
3554
  getInstalledSdks,
@@ -3248,6 +3566,8 @@ var VERSION = "0.7.0";
3248
3566
  installEmulator,
3249
3567
  isCmdToolsInstalled,
3250
3568
  isEmulatorInstalled,
3569
+ isOutOfSpaceError,
3570
+ isRamBackedPath,
3251
3571
  isValidBundleName,
3252
3572
  isValidProjectName,
3253
3573
  launchApp,
@@ -3265,6 +3585,8 @@ var VERSION = "0.7.0";
3265
3585
  parseCodelinterFindings,
3266
3586
  parseDeviceList,
3267
3587
  parseHilogLine,
3588
+ parseMainAbilityFromBmDump,
3589
+ parseRemoteExit,
3268
3590
  pickSigningKind,
3269
3591
  prepareSigning,
3270
3592
  pruneLayout,
@@ -3275,6 +3597,8 @@ var VERSION = "0.7.0";
3275
3597
  removeCmdTools,
3276
3598
  removeEmulator,
3277
3599
  removeSdk,
3600
+ removeTempWorkDir,
3601
+ resolveTmpRoot,
3278
3602
  runCodelinter,
3279
3603
  runHvigorw,
3280
3604
  runOhpm,
@@ -3287,11 +3611,13 @@ var VERSION = "0.7.0";
3287
3611
  sendRawTouch,
3288
3612
  setHilogLevel,
3289
3613
  shell,
3614
+ shellChecked,
3290
3615
  startEmulator,
3291
3616
  staticConfig,
3292
3617
  stopEmulator,
3293
3618
  streamHilog,
3294
3619
  takeScreenshot,
3620
+ toSpaceError,
3295
3621
  uninstallApp,
3296
3622
  validateTemplateLayout,
3297
3623
  verifySha256,
@@ -3300,6 +3626,7 @@ var VERSION = "0.7.0";
3300
3626
  waitForCondition,
3301
3627
  waitForLog,
3302
3628
  watchLog,
3629
+ waypointsToRawEvents,
3303
3630
  writeJson5File,
3304
3631
  writeJsonFile
3305
3632
  });