@oniroproject/core 0.14.1 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  HUAWEI_SITES: () => HUAWEI_SITES,
43
43
  INSTALL_TMP_DIRNAME: () => INSTALL_TMP_DIRNAME,
44
44
  InsufficientSpaceError: () => InsufficientSpaceError,
45
+ OHOS_DAILY_BUILDS_URL: () => OHOS_DAILY_BUILDS_URL,
45
46
  OHOS_URL_BASE: () => OHOS_URL_BASE,
46
47
  OniroError: () => OniroError,
47
48
  SIGNING_ERRORS: () => SIGNING_ERRORS,
@@ -62,6 +63,7 @@ __export(index_exports, {
62
63
  buildHvigorwArgs: () => buildHvigorwArgs,
63
64
  buildInputCommand: () => buildInputCommand,
64
65
  buildRawTouchCommand: () => buildRawTouchCommand,
66
+ bundleNameFromHapConfig: () => bundleNameFromHapConfig,
65
67
  captureBurst: () => captureBurst,
66
68
  captureLog: () => captureLog,
67
69
  cleanCodelinterOutput: () => cleanCodelinterOutput,
@@ -115,6 +117,7 @@ __export(index_exports, {
115
117
  findLayoutNodes: () => findLayoutNodes,
116
118
  findMissingProjectSdk: () => findMissingProjectSdk,
117
119
  findRunningProcess: () => findRunningProcess,
120
+ findSdkOsDir: () => findSdkOsDir,
118
121
  flattenLayout: () => flattenLayout,
119
122
  forceStop: () => forceStop,
120
123
  formatBytes: () => formatBytes,
@@ -148,16 +151,19 @@ __export(index_exports, {
148
151
  hdcTargetArgs: () => hdcTargetArgs,
149
152
  hdcTargetArgsFor: () => hdcTargetArgsFor,
150
153
  hideKeyboard: () => hideKeyboard,
154
+ hilogTimeMs: () => hilogTimeMs,
151
155
  installApp: () => installApp,
152
156
  installCmdTools: () => installCmdTools,
153
157
  installEmulator: () => installEmulator,
154
158
  installFailureReason: () => installFailureReason,
159
+ installSdkFromArchive: () => installSdkFromArchive,
155
160
  isBundleInstalled: () => isBundleInstalled,
156
161
  isCmdToolsInstalled: () => isCmdToolsInstalled,
157
162
  isEmulatorInstalled: () => isEmulatorInstalled,
158
163
  isOutOfSpaceError: () => isOutOfSpaceError,
159
164
  isRamBackedPath: () => isRamBackedPath,
160
165
  isUnsignedHap: () => isUnsignedHap,
166
+ isUsableDevice: () => isUsableDevice,
161
167
  isValidBundleName: () => isValidBundleName,
162
168
  isValidProjectName: () => isValidProjectName,
163
169
  killProcessTree: () => killProcessTree,
@@ -168,6 +174,7 @@ __export(index_exports, {
168
174
  listRunningProcesses: () => listRunningProcesses,
169
175
  listTemplates: () => listTemplates,
170
176
  locateTarget: () => locateTarget,
177
+ missingProjectRootFiles: () => missingProjectRootFiles,
171
178
  needsCmdWrapper: () => needsCmdWrapper,
172
179
  nonInteractivePrompter: () => nonInteractivePrompter,
173
180
  noopLogger: () => noopLogger,
@@ -191,9 +198,11 @@ __export(index_exports, {
191
198
  pickTarget: () => pickTarget,
192
199
  prepareSigning: () => prepareSigning,
193
200
  pruneLayout: () => pruneLayout,
201
+ readHapBundleName: () => readHapBundleName,
194
202
  readJson5File: () => readJson5File,
195
203
  readJsonFile: () => readJsonFile,
196
204
  readProvisionProfile: () => readProvisionProfile,
205
+ readZipEntry: () => readZipEntry,
197
206
  reboot: () => reboot,
198
207
  recvFile: () => recvFile,
199
208
  removeCmdTools: () => removeCmdTools,
@@ -424,6 +433,7 @@ var ALL_SDKS = [
424
433
  { version: "7.0", api: "26", tarballStrip: { linuxWindows: 1, darwin: 3 }, archiveSuffix: "_20260829" }
425
434
  ];
426
435
  var OHOS_URL_BASE = "https://repo.huaweicloud.com/openharmony/os";
436
+ var OHOS_DAILY_BUILDS_URL = "https://dcp.openharmony.cn/workbench/cicd/dailybuild/dailylist";
427
437
 
428
438
  // src/sdk/platform.ts
429
439
  var os2 = __toESM(require("os"), 1);
@@ -1006,8 +1016,17 @@ async function extractZipWithProgress(opts) {
1006
1016
  if (inc > 0) progress.report({ message: "Extracting: 100%", increment: inc });
1007
1017
  }
1008
1018
  }
1009
- async function extractTarball(tarPath, dest, strip = 0) {
1010
- await tar.x({ file: tarPath, cwd: dest, strip });
1019
+ async function extractTarball(tarPath, dest, strip = 0, filter) {
1020
+ await tar.x({ file: tarPath, cwd: dest, strip, ...filter ? { filter: (p) => filter(p) } : {} });
1021
+ }
1022
+ async function readZipEntry(zipPath, match) {
1023
+ const zip = new import_node_stream_zip.default.async({ file: zipPath });
1024
+ try {
1025
+ const entry = Object.values(await zip.entries()).find((e) => !e.isDirectory && match(e.name));
1026
+ return entry ? await zip.entryData(entry) : void 0;
1027
+ } finally {
1028
+ await zip.close();
1029
+ }
1011
1030
  }
1012
1031
 
1013
1032
  // src/sdk/list.ts
@@ -1113,34 +1132,7 @@ async function downloadAndInstallSdk(opts) {
1113
1132
  `Expected folder '${osFolder}' not found in extracted SDK. Tarball layout may have changed.`
1114
1133
  );
1115
1134
  }
1116
- const zipFiles = fs10.readdirSync(osContentPath).filter((n2) => n2.endsWith(".zip"));
1117
- const componentsStart = 60;
1118
- const componentsBudget = 35;
1119
- const n = zipFiles.length;
1120
- if (n === 0) {
1121
- progress?.report({ message: "No SDK component ZIPs found.", increment: componentsBudget });
1122
- } else {
1123
- progress?.report({ message: "Extracting SDK components...", increment: 0 });
1124
- }
1125
- const base = n > 0 ? Math.floor(componentsBudget / n) : 0;
1126
- let rem = n > 0 ? componentsBudget % n : 0;
1127
- let cursor = componentsStart;
1128
- for (const zipFile of zipFiles) {
1129
- checkCancelled();
1130
- logger.info(`Extracting component ${zipFile}`);
1131
- const zipPath = path10.join(osContentPath, zipFile);
1132
- const thisBudget = base + (rem > 0 ? 1 : 0);
1133
- if (rem > 0) rem--;
1134
- await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });
1135
- cursor += thisBudget;
1136
- fs10.unlinkSync(zipPath);
1137
- }
1138
- progress?.report({ message: "Finalizing installation...", increment: 0 });
1139
- if (fs10.existsSync(sdkInstallDir)) {
1140
- fs10.rmSync(sdkInstallDir, { recursive: true, force: true });
1141
- }
1142
- movePath(osContentPath, sdkInstallDir);
1143
- progress?.report({ message: "Finalizing installation...", increment: 3 });
1135
+ await installComponents({ osContentPath, sdkInstallDir, progress, logger, start: 60, range: 35, checkCancelled });
1144
1136
  progress?.report({ message: "Cleaning up...", increment: 0 });
1145
1137
  removeTempWorkDir(tmpDir, tmpRoot);
1146
1138
  progress?.report({ message: "Cleaning up...", increment: 2 });
@@ -1151,6 +1143,115 @@ async function downloadAndInstallSdk(opts) {
1151
1143
  throw wrapped;
1152
1144
  }
1153
1145
  }
1146
+ async function installComponents(opts) {
1147
+ const { osContentPath, sdkInstallDir, progress, logger, checkCancelled } = opts;
1148
+ const zipFiles = fs10.readdirSync(osContentPath).filter((n2) => n2.endsWith(".zip"));
1149
+ const n = zipFiles.length;
1150
+ if (n === 0) {
1151
+ progress?.report({ message: "No SDK component ZIPs found.", increment: opts.range });
1152
+ } else {
1153
+ progress?.report({ message: "Extracting SDK components...", increment: 0 });
1154
+ }
1155
+ const base = n > 0 ? Math.floor(opts.range / n) : 0;
1156
+ let rem = n > 0 ? opts.range % n : 0;
1157
+ let cursor = opts.start;
1158
+ for (const zipFile of zipFiles) {
1159
+ checkCancelled();
1160
+ logger.info(`Extracting component ${zipFile}`);
1161
+ const zipPath = path10.join(osContentPath, zipFile);
1162
+ const thisBudget = base + (rem > 0 ? 1 : 0);
1163
+ if (rem > 0) rem--;
1164
+ await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });
1165
+ cursor += thisBudget;
1166
+ fs10.unlinkSync(zipPath);
1167
+ }
1168
+ progress?.report({ message: "Finalizing installation...", increment: 0 });
1169
+ if (fs10.existsSync(sdkInstallDir)) {
1170
+ fs10.rmSync(sdkInstallDir, { recursive: true, force: true });
1171
+ }
1172
+ movePath(osContentPath, sdkInstallDir);
1173
+ progress?.report({ message: "Finalizing installation...", increment: 3 });
1174
+ }
1175
+ async function installSdkFromArchive(opts) {
1176
+ const { config, archivePath, progress, abortSignal } = opts;
1177
+ const logger = opts.logger ?? noopLogger;
1178
+ if (!fs10.statSync(archivePath, { throwIfNoEntry: false })?.isFile()) {
1179
+ throw new OniroError(`SDK archive not found: ${archivePath}`);
1180
+ }
1181
+ const osFolder = getOsFolder();
1182
+ const what = `the SDK install from '${path10.basename(archivePath)}'`;
1183
+ const sdkRoot = getSdkRootDir(config);
1184
+ const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
1185
+ config,
1186
+ override: opts.tmpDir,
1187
+ installRoot: sdkRoot,
1188
+ prefix: "oniro-sdk-",
1189
+ logger
1190
+ });
1191
+ const extractDir = path10.join(tmpDir, "extract");
1192
+ fs10.mkdirSync(extractDir);
1193
+ const checkCancelled = () => {
1194
+ if (abortSignal?.aborted) throw new CancelledError();
1195
+ };
1196
+ try {
1197
+ progress?.report({ message: "Extracting SDK archive (this may take a while)...", increment: 0 });
1198
+ await extractTarball(archivePath, extractDir, 0, (p) => p.split("/").includes(osFolder));
1199
+ progress?.report({ message: "Extracting SDK archive (this may take a while)...", increment: 40 });
1200
+ checkCancelled();
1201
+ const osContentPath = findSdkOsDir(extractDir, osFolder);
1202
+ if (!osContentPath) {
1203
+ throw new OniroError(
1204
+ `No '${osFolder}' SDK components (a '${osFolder}' folder of ZIPs) found in ${archivePath}. Is it an OpenHarmony SDK archive for this OS?`
1205
+ );
1206
+ }
1207
+ const { api, version } = await readSdkComponentsMeta(osContentPath);
1208
+ const sdkInstallDir = path10.join(sdkRoot, osFolder, api);
1209
+ if (fs10.existsSync(sdkInstallDir) && !opts.force) {
1210
+ throw new OniroError(
1211
+ `An SDK for api ${api} is already installed at ${sdkInstallDir}; pass --force to replace it with this archive, or set ONIRO_SDK_ROOT_DIR to install it in a separate SDK root.`
1212
+ );
1213
+ }
1214
+ fs10.mkdirSync(path10.dirname(sdkInstallDir), { recursive: true });
1215
+ await installComponents({ osContentPath, sdkInstallDir, progress, logger, start: 40, range: 55, checkCancelled });
1216
+ progress?.report({ message: "Cleaning up...", increment: 0 });
1217
+ removeTempWorkDir(tmpDir, tmpRoot);
1218
+ progress?.report({ message: "Cleaning up...", increment: 2 });
1219
+ return { api, version, dir: sdkInstallDir };
1220
+ } catch (err) {
1221
+ removeTempWorkDir(tmpDir, tmpRoot);
1222
+ throw toSpaceError(err, tmpRoot, what);
1223
+ }
1224
+ }
1225
+ function findSdkOsDir(root, osFolder, maxDepth = 4) {
1226
+ let level = [root];
1227
+ for (let depth = 0; depth < maxDepth && level.length > 0; depth++) {
1228
+ const next = [];
1229
+ for (const dir of level) {
1230
+ for (const entry of fs10.readdirSync(dir, { withFileTypes: true })) {
1231
+ if (!entry.isDirectory()) continue;
1232
+ const p = path10.join(dir, entry.name);
1233
+ if (entry.name === osFolder && fs10.readdirSync(p).some((n) => n.endsWith(".zip"))) return p;
1234
+ next.push(p);
1235
+ }
1236
+ }
1237
+ level = next;
1238
+ }
1239
+ return void 0;
1240
+ }
1241
+ async function readSdkComponentsMeta(dir) {
1242
+ const zips = fs10.readdirSync(dir).filter((n) => n.endsWith(".zip")).sort((a, b) => Number(b.startsWith("ets-")) - Number(a.startsWith("ets-")));
1243
+ for (const name of zips) {
1244
+ const data = await readZipEntry(path10.join(dir, name), (e) => /^[^/]+\/oh-uni-package\.json$/.test(e));
1245
+ if (!data) continue;
1246
+ try {
1247
+ const pkg = JSON.parse(data.toString("utf8"));
1248
+ const api = String(pkg.apiVersion ?? "");
1249
+ if (/^\d+$/.test(api)) return { api, version: String(pkg.version ?? "") };
1250
+ } catch {
1251
+ }
1252
+ }
1253
+ throw new OniroError("No SDK component in the archive declares a numeric apiVersion (oh-uni-package.json).");
1254
+ }
1154
1255
 
1155
1256
  // src/cmdTools/install.ts
1156
1257
  var fs11 = __toESM(require("fs"), 1);
@@ -2242,12 +2343,13 @@ async function listDevices(config, opts = {}) {
2242
2343
  });
2243
2344
  return parseDeviceList(res.stdout);
2244
2345
  }
2346
+ function isUsableDevice(device) {
2347
+ return device.status === "Connected" || device.status === "Unknown";
2348
+ }
2245
2349
  async function selectDevice(config, serial, opts = {}) {
2246
2350
  const resolved = resolveDeviceSerial(serial);
2247
2351
  if (resolved) return resolved;
2248
- const usable = (await listDevices(config, opts)).filter(
2249
- (d) => d.status === "Connected" || d.status === "Unknown"
2250
- );
2352
+ const usable = (await listDevices(config, opts)).filter(isUsableDevice);
2251
2353
  if (usable.length === 1) return usable[0].serial;
2252
2354
  if (usable.length === 0) {
2253
2355
  throw new OniroError("No connected device found. Connect a device/emulator or set ONIRO_DEVICE_SERIAL.");
@@ -2438,9 +2540,13 @@ function moduleOfHap(hapFileName) {
2438
2540
  const dash = hapFileName.indexOf("-");
2439
2541
  return dash > 0 ? hapFileName.slice(0, dash) : hapFileName.replace(/\.hap$/i, "");
2440
2542
  }
2543
+ function isAppProjectRoot(dir) {
2544
+ return fs17.existsSync(path18.join(dir, "AppScope", "app.json5"));
2545
+ }
2441
2546
  async function discoverHaps(opts) {
2442
2547
  const { projectDir } = opts;
2443
2548
  const maxDepth = opts.maxDepth ?? 8;
2549
+ const skipNestedProjects = isAppProjectRoot(projectDir);
2444
2550
  const result = {};
2445
2551
  const walk = async (dir, depth) => {
2446
2552
  if (depth > maxDepth) return;
@@ -2449,6 +2555,7 @@ async function discoverHaps(opts) {
2449
2555
  const full = path18.join(dir, e.name);
2450
2556
  if (e.isDirectory()) {
2451
2557
  if (e.name === "node_modules" || e.name === "oh_modules" || e.name === ".git") continue;
2558
+ if (skipNestedProjects && isAppProjectRoot(full)) continue;
2452
2559
  await walk(full, depth + 1);
2453
2560
  } else if (e.isFile() && e.name.endsWith(".hap")) {
2454
2561
  const moduleName = moduleOfHap(e.name);
@@ -3640,6 +3747,54 @@ async function resolveProcessId(config, bundle, deviceSerial) {
3640
3747
  const proc = await findRunningProcess({ config, bundle, deviceSerial });
3641
3748
  return proc?.pid;
3642
3749
  }
3750
+ async function readDeviceClock(config, deviceSerial) {
3751
+ try {
3752
+ const res = await shell({ config, command: "date +%Y-%m-%dT%H:%M:%S", deviceSerial, timeoutMs: 1e4 });
3753
+ const m = res.code === 0 ? /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/.exec(res.stdout) : null;
3754
+ if (!m) return null;
3755
+ const [year, month, day, hour, minute, second] = m.slice(1).map(Number);
3756
+ return Date.UTC(year, month - 1, day, hour, minute, second);
3757
+ } catch {
3758
+ return null;
3759
+ }
3760
+ }
3761
+ function hilogTimeMs(time, referenceMs) {
3762
+ const m = /^(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})\.(\d{3})$/.exec(time);
3763
+ if (!m) return null;
3764
+ const [month, day, hour, minute, second, ms] = m.slice(1).map(Number);
3765
+ const year = new Date(referenceMs).getUTCFullYear();
3766
+ let best = null;
3767
+ for (const y of [year - 1, year, year + 1]) {
3768
+ const t = Date.UTC(y, month - 1, day, hour, minute, second, ms);
3769
+ if (best === null || Math.abs(t - referenceMs) < Math.abs(best - referenceMs)) best = t;
3770
+ }
3771
+ return best;
3772
+ }
3773
+ async function recentEntryFilter(opts) {
3774
+ const passAll = { test: () => true, afterReconnect: async () => {
3775
+ } };
3776
+ const lookbackMs = opts.lookbackMs ?? 0;
3777
+ if (lookbackMs === Infinity) return passAll;
3778
+ const startedAt = Date.now();
3779
+ const now = await readDeviceClock(opts.config, opts.deviceSerial);
3780
+ if (now === null) {
3781
+ opts.logger.warn("Could not read the device clock, so lines already in the log buffer can match too.");
3782
+ return passAll;
3783
+ }
3784
+ let since = now - (Date.now() - startedAt) - lookbackMs;
3785
+ return {
3786
+ test: (entry) => {
3787
+ if (since === null) return true;
3788
+ const t = hilogTimeMs(entry.time, now);
3789
+ return t === null || t >= since;
3790
+ },
3791
+ afterReconnect: async () => {
3792
+ if (since === null) return;
3793
+ const later = await readDeviceClock(opts.config, opts.deviceSerial);
3794
+ if (later !== null && later < since) since = null;
3795
+ }
3796
+ };
3797
+ }
3643
3798
  function waitForLog(opts) {
3644
3799
  return new Promise((resolve7, reject) => {
3645
3800
  const deadline = Date.now() + opts.timeoutMs;
@@ -3647,6 +3802,8 @@ function waitForLog(opts) {
3647
3802
  let child = null;
3648
3803
  let reconnectTimer;
3649
3804
  let buf = "";
3805
+ let recent = { test: () => true, afterReconnect: async () => {
3806
+ } };
3650
3807
  const cleanup = () => {
3651
3808
  clearTimeout(timer);
3652
3809
  if (reconnectTimer) clearTimeout(reconnectTimer);
@@ -3687,7 +3844,7 @@ function waitForLog(opts) {
3687
3844
  buf = lines.pop() ?? "";
3688
3845
  for (const line of lines) {
3689
3846
  const entry = parseHilogLine(line);
3690
- if (entry && opts.pattern.test(entryText(entry))) {
3847
+ if (entry && recent.test(entry) && opts.pattern.test(entryText(entry))) {
3691
3848
  finish(entry);
3692
3849
  return;
3693
3850
  }
@@ -3697,13 +3854,21 @@ function waitForLog(opts) {
3697
3854
  if (settled || child !== stream) return;
3698
3855
  child = null;
3699
3856
  if (Date.now() < deadline) {
3700
- reconnectTimer = setTimeout(() => void spawnStream().catch(failWith), 1e3);
3857
+ reconnectTimer = setTimeout(() => void recent.afterReconnect().then(spawnStream).catch(failWith), 1e3);
3701
3858
  }
3702
3859
  };
3703
3860
  stream.once("close", onEnd);
3704
3861
  stream.once("error", onEnd);
3705
3862
  };
3706
- void spawnStream().catch(failWith);
3863
+ void (async () => {
3864
+ recent = await recentEntryFilter({
3865
+ config: opts.config,
3866
+ deviceSerial: opts.deviceSerial,
3867
+ lookbackMs: opts.lookbackMs,
3868
+ logger: opts.logger ?? noopLogger
3869
+ });
3870
+ await spawnStream();
3871
+ })().catch(failWith);
3707
3872
  });
3708
3873
  }
3709
3874
  function watchLog(opts) {
@@ -3712,6 +3877,8 @@ function watchLog(opts) {
3712
3877
  let settled = false;
3713
3878
  let child = null;
3714
3879
  let buf = "";
3880
+ let recent = { test: () => true, afterReconnect: async () => {
3881
+ } };
3715
3882
  const cleanup = () => {
3716
3883
  clearTimeout(timer);
3717
3884
  opts.abortSignal?.removeEventListener("abort", onAbort);
@@ -3735,6 +3902,13 @@ function watchLog(opts) {
3735
3902
  const timer = setTimeout(done, opts.durationMs);
3736
3903
  opts.abortSignal?.addEventListener("abort", onAbort, { once: true });
3737
3904
  void (async () => {
3905
+ recent = await recentEntryFilter({
3906
+ config: opts.config,
3907
+ deviceSerial: opts.deviceSerial,
3908
+ lookbackMs: opts.lookbackMs,
3909
+ logger: opts.logger ?? noopLogger
3910
+ });
3911
+ if (settled) return;
3738
3912
  const processId = await resolveProcessId(opts.config, opts.bundle, opts.deviceSerial);
3739
3913
  if (settled) return;
3740
3914
  const stream = streamHilog({ config: opts.config, processId, domain: opts.domain, deviceSerial: opts.deviceSerial });
@@ -3745,7 +3919,7 @@ function watchLog(opts) {
3745
3919
  buf = lines.pop() ?? "";
3746
3920
  for (const line of lines) {
3747
3921
  const entry = parseHilogLine(line);
3748
- if (entry && opts.pattern.test(entryText(entry))) matches.push(entry);
3922
+ if (entry && recent.test(entry) && opts.pattern.test(entryText(entry))) matches.push(entry);
3749
3923
  }
3750
3924
  });
3751
3925
  })().catch((err) => {
@@ -4030,6 +4204,8 @@ async function ensureOhModules(opts) {
4030
4204
  }
4031
4205
 
4032
4206
  // src/build/codelinter.ts
4207
+ var fs26 = __toESM(require("fs"), 1);
4208
+ var path26 = __toESM(require("path"), 1);
4033
4209
  var FINDING_RE = /^(.*?):(\d+):(?:(\d+):)?\s*(error|warning|warn|suggestion|info)\b[:\s-]*(.*)$/i;
4034
4210
  var TRAILING_CODE_RE = /[([]([\w@/.\-]+)[)\]]\s*$/;
4035
4211
  var FILE_HEADER_RE = /^(.+\.\w+)\((\d+)\)$/;
@@ -4116,6 +4292,16 @@ function parseCodelinterReport(output) {
4116
4292
  function parseCodelinterFindings(output) {
4117
4293
  return parseCodelinterReport(output).findings;
4118
4294
  }
4295
+ var PROJECT_ROOT_FILES = [
4296
+ ["build-profile.json5"],
4297
+ ["hvigorfile.ts", "hvigorfile.js"],
4298
+ [path26.join("hvigor", "hvigor-config.json5")]
4299
+ ];
4300
+ function missingProjectRootFiles(projectDir) {
4301
+ return PROJECT_ROOT_FILES.filter((names) => !names.some((f) => fs26.existsSync(path26.join(projectDir, f)))).map(
4302
+ (names) => names[0]
4303
+ );
4304
+ }
4119
4305
  async function runCodelinter(opts) {
4120
4306
  const res = await runProcess({
4121
4307
  command: getCmdToolsBin(opts.config, "codelinter"),
@@ -4133,7 +4319,7 @@ async function runCodelinter(opts) {
4133
4319
  var DIAGNOSIS_OUTPUT_LIMIT = 2e6;
4134
4320
  function diagnoseBuildFailure(output) {
4135
4321
  if (/is not exported from Kit|has no exported member .*@systemapi/i.test(output)) {
4136
- return "The project calls system APIs (`@systemapi`), which the public SDK leaves out. Build against the full OpenHarmony SDK: unpack its components into <root>/<os>/<api> of a separate SDK root and set ONIRO_SDK_ROOT_DIR to that root. Installing such an app also needs privileged signing (`oniro-app sign --apl system_core --acls \u2026 --app-privilege-capabilities \u2026`).";
4322
+ return `The project calls system APIs (\`@systemapi\`), which the public SDK leaves out. Build against the full OpenHarmony SDK: download an \`ohos-sdk-full\` archive from ${OHOS_DAILY_BUILDS_URL} and install it with \`oniro-app sdk install --from-archive <archive> --force\` (this replaces the public SDK of that API level; set ONIRO_SDK_ROOT_DIR to keep the two apart). Installing such an app also needs privileged signing (\`oniro-app sign --apl system_core --acls \u2026 --app-privilege-capabilities \u2026\`).`;
4137
4323
  }
4138
4324
  if (/00308018|SDK path does not exist|SDK license agreement is not accepted/i.test(output)) {
4139
4325
  return "hvigor cannot find the SDK the project compiles against: check `oniro-app sdk list` against compileSdkVersion.";
@@ -4205,21 +4391,21 @@ function isValidBundleName(bundleName) {
4205
4391
  }
4206
4392
 
4207
4393
  // src/project/templates.ts
4208
- var fs26 = __toESM(require("fs"), 1);
4209
- var path26 = __toESM(require("path"), 1);
4394
+ var fs27 = __toESM(require("fs"), 1);
4395
+ var path27 = __toESM(require("path"), 1);
4210
4396
  function toHumanTemplateName(folderName) {
4211
4397
  return folderName.replace(/([a-z])([A-Z])/g, "$1 $2");
4212
4398
  }
4213
4399
  function listTemplates(templateRoot) {
4214
- if (!fs26.existsSync(templateRoot)) return [];
4215
- const entries = fs26.readdirSync(templateRoot, { withFileTypes: true });
4400
+ if (!fs27.existsSync(templateRoot)) return [];
4401
+ const entries = fs27.readdirSync(templateRoot, { withFileTypes: true });
4216
4402
  return entries.filter((e) => e.isDirectory()).map((e) => {
4217
- const dir = path26.join(templateRoot, e.name);
4218
- const metaPath = path26.join(dir, "template.json");
4403
+ const dir = path27.join(templateRoot, e.name);
4404
+ const metaPath = path27.join(dir, "template.json");
4219
4405
  let meta = {};
4220
- if (fs26.existsSync(metaPath)) {
4406
+ if (fs27.existsSync(metaPath)) {
4221
4407
  try {
4222
- meta = JSON.parse(fs26.readFileSync(metaPath, "utf8"));
4408
+ meta = JSON.parse(fs27.readFileSync(metaPath, "utf8"));
4223
4409
  } catch {
4224
4410
  }
4225
4411
  }
@@ -4234,57 +4420,57 @@ function listTemplates(templateRoot) {
4234
4420
  function validateTemplateLayout(templateDir, defaultModuleName) {
4235
4421
  const required = [
4236
4422
  "build-profile.json5",
4237
- path26.join("AppScope", "app.json5"),
4238
- path26.join(defaultModuleName, "src", "main", "module.json5"),
4239
- path26.join(defaultModuleName, "oh-package.json5"),
4423
+ path27.join("AppScope", "app.json5"),
4424
+ path27.join(defaultModuleName, "src", "main", "module.json5"),
4425
+ path27.join(defaultModuleName, "oh-package.json5"),
4240
4426
  "hvigorfile.ts"
4241
4427
  ];
4242
- return required.filter((rel) => !fs26.existsSync(path26.join(templateDir, rel)));
4428
+ return required.filter((rel) => !fs27.existsSync(path27.join(templateDir, rel)));
4243
4429
  }
4244
4430
 
4245
4431
  // src/project/createScaffold.ts
4246
- var fs28 = __toESM(require("fs"), 1);
4247
- var path27 = __toESM(require("path"), 1);
4432
+ var fs29 = __toESM(require("fs"), 1);
4433
+ var path28 = __toESM(require("path"), 1);
4248
4434
 
4249
4435
  // src/project/jsonHelpers.ts
4250
- var fs27 = __toESM(require("fs"), 1);
4436
+ var fs28 = __toESM(require("fs"), 1);
4251
4437
  var import_json55 = __toESM(require("json5"), 1);
4252
4438
  function readJson5File(filePath) {
4253
- return import_json55.default.parse(fs27.readFileSync(filePath, "utf8"));
4439
+ return import_json55.default.parse(fs28.readFileSync(filePath, "utf8"));
4254
4440
  }
4255
4441
  function writeJson5File(filePath, value) {
4256
- fs27.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
4442
+ fs28.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
4257
4443
  }
4258
4444
  function readJsonFile(filePath) {
4259
- return JSON.parse(fs27.readFileSync(filePath, "utf8"));
4445
+ return JSON.parse(fs28.readFileSync(filePath, "utf8"));
4260
4446
  }
4261
4447
  function writeJsonFile(filePath, value) {
4262
- fs27.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
4448
+ fs28.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
4263
4449
  }
4264
4450
 
4265
4451
  // src/project/createScaffold.ts
4266
4452
  var IGNORED_DIRS = /* @__PURE__ */ new Set(["oh_modules", "node_modules", "build", ".hvigor"]);
4267
4453
  async function pathExists(p) {
4268
4454
  try {
4269
- await fs28.promises.access(p);
4455
+ await fs29.promises.access(p);
4270
4456
  return true;
4271
4457
  } catch {
4272
4458
  return false;
4273
4459
  }
4274
4460
  }
4275
4461
  async function copyDirRecursive(srcDir, destDir) {
4276
- await fs28.promises.mkdir(destDir, { recursive: true });
4277
- const entries = await fs28.promises.readdir(srcDir, { withFileTypes: true });
4462
+ await fs29.promises.mkdir(destDir, { recursive: true });
4463
+ const entries = await fs29.promises.readdir(srcDir, { withFileTypes: true });
4278
4464
  for (const entry of entries) {
4279
- const src = path27.join(srcDir, entry.name);
4280
- const dest = path27.join(destDir, entry.name);
4465
+ const src = path28.join(srcDir, entry.name);
4466
+ const dest = path28.join(destDir, entry.name);
4281
4467
  if (entry.isDirectory()) {
4282
4468
  await copyDirRecursive(src, dest);
4283
4469
  } else if (entry.isSymbolicLink()) {
4284
4470
  continue;
4285
4471
  } else if (entry.isFile()) {
4286
4472
  if (entry.name === "template.json") continue;
4287
- await fs28.promises.copyFile(src, dest);
4473
+ await fs29.promises.copyFile(src, dest);
4288
4474
  }
4289
4475
  }
4290
4476
  }
@@ -4292,9 +4478,9 @@ async function normalizeJson5ToJson(projectDir, logger) {
4292
4478
  const stack = [projectDir];
4293
4479
  while (stack.length > 0) {
4294
4480
  const currentDir = stack.pop();
4295
- const entries = await fs28.promises.readdir(currentDir, { withFileTypes: true });
4481
+ const entries = await fs29.promises.readdir(currentDir, { withFileTypes: true });
4296
4482
  for (const entry of entries) {
4297
- const fullPath = path27.join(currentDir, entry.name);
4483
+ const fullPath = path28.join(currentDir, entry.name);
4298
4484
  if (entry.isDirectory()) {
4299
4485
  if (IGNORED_DIRS.has(entry.name)) continue;
4300
4486
  stack.push(fullPath);
@@ -4316,23 +4502,23 @@ function toJavaPropertiesPath(p) {
4316
4502
  function createOrUpdateLocalProperties(projectDir, sdkDir) {
4317
4503
  const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}
4318
4504
  `;
4319
- fs28.writeFileSync(path27.join(projectDir, "local.properties"), content, "utf8");
4505
+ fs29.writeFileSync(path28.join(projectDir, "local.properties"), content, "utf8");
4320
4506
  }
4321
4507
  function renameIfExists(fromPath, toPath) {
4322
- if (fs28.existsSync(fromPath) && fromPath !== toPath) {
4323
- fs28.renameSync(fromPath, toPath);
4508
+ if (fs29.existsSync(fromPath) && fromPath !== toPath) {
4509
+ fs29.renameSync(fromPath, toPath);
4324
4510
  }
4325
4511
  }
4326
4512
  function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
4327
- const appJsonPath = path27.join(projectDir, "AppScope", "app.json5");
4328
- if (fs28.existsSync(appJsonPath)) {
4513
+ const appJsonPath = path28.join(projectDir, "AppScope", "app.json5");
4514
+ if (fs29.existsSync(appJsonPath)) {
4329
4515
  const appJson = readJson5File(appJsonPath);
4330
4516
  appJson.app = appJson.app ?? {};
4331
4517
  appJson.app.bundleName = args.bundleName;
4332
4518
  writeJson5File(appJsonPath, appJson);
4333
4519
  }
4334
- const stringsPath = path27.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
4335
- if (fs28.existsSync(stringsPath)) {
4520
+ const stringsPath = path28.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
4521
+ if (fs29.existsSync(stringsPath)) {
4336
4522
  const strings = readJsonFile(stringsPath);
4337
4523
  if (Array.isArray(strings.string)) {
4338
4524
  const appName = strings.string.find((s) => s.name === "app_name");
@@ -4340,8 +4526,8 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
4340
4526
  }
4341
4527
  writeJsonFile(stringsPath, strings);
4342
4528
  }
4343
- const buildProfilePath = path27.join(projectDir, "build-profile.json5");
4344
- if (fs28.existsSync(buildProfilePath)) {
4529
+ const buildProfilePath = path28.join(projectDir, "build-profile.json5");
4530
+ if (fs29.existsSync(buildProfilePath)) {
4345
4531
  const buildProfile = readJson5File(buildProfilePath);
4346
4532
  buildProfile.app = buildProfile.app ?? {};
4347
4533
  if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {
@@ -4354,23 +4540,23 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
4354
4540
  }
4355
4541
  writeJson5File(buildProfilePath, buildProfile);
4356
4542
  }
4357
- const moduleJsonPath = path27.join(projectDir, args.moduleName, "src", "main", "module.json5");
4358
- if (fs28.existsSync(moduleJsonPath)) {
4543
+ const moduleJsonPath = path28.join(projectDir, args.moduleName, "src", "main", "module.json5");
4544
+ if (fs29.existsSync(moduleJsonPath)) {
4359
4545
  const moduleJson = readJson5File(moduleJsonPath);
4360
4546
  moduleJson.module = moduleJson.module ?? {};
4361
4547
  moduleJson.module.name = args.moduleName;
4362
4548
  writeJson5File(moduleJsonPath, moduleJson);
4363
4549
  }
4364
- const moduleOhPackagePath = path27.join(projectDir, args.moduleName, "oh-package.json5");
4365
- if (fs28.existsSync(moduleOhPackagePath)) {
4550
+ const moduleOhPackagePath = path28.join(projectDir, args.moduleName, "oh-package.json5");
4551
+ if (fs29.existsSync(moduleOhPackagePath)) {
4366
4552
  const pkg = readJson5File(moduleOhPackagePath);
4367
4553
  pkg.name = args.moduleName;
4368
4554
  writeJson5File(moduleOhPackagePath, pkg);
4369
4555
  }
4370
- const vscodeDir = path27.join(projectDir, ".vscode");
4371
- fs28.mkdirSync(vscodeDir, { recursive: true });
4556
+ const vscodeDir = path28.join(projectDir, ".vscode");
4557
+ fs29.mkdirSync(vscodeDir, { recursive: true });
4372
4558
  const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;
4373
- writeJsonFile(path27.join(vscodeDir, "settings.json"), {
4559
+ writeJsonFile(path28.join(vscodeDir, "settings.json"), {
4374
4560
  "oniro.hapPath": hapPath,
4375
4561
  "files.associations": { "*.json5": "jsonc" }
4376
4562
  });
@@ -4387,7 +4573,7 @@ async function createScaffold(opts) {
4387
4573
  if (!opts.location || !await pathExists(opts.location)) {
4388
4574
  throw new OniroError(`Location does not exist: ${opts.location}`);
4389
4575
  }
4390
- const templateDir = path27.join(opts.templateRoot, opts.templateId);
4576
+ const templateDir = path28.join(opts.templateRoot, opts.templateId);
4391
4577
  if (!await pathExists(templateDir)) {
4392
4578
  throw new OniroError(`Template not found: ${templateDir}`);
4393
4579
  }
@@ -4422,17 +4608,17 @@ async function createScaffold(opts) {
4422
4608
  }
4423
4609
  }
4424
4610
  }
4425
- const projectDir = path27.join(opts.location, opts.projectName);
4611
+ const projectDir = path28.join(opts.location, opts.projectName);
4426
4612
  if (await pathExists(projectDir)) {
4427
4613
  if (!opts.overwrite) {
4428
4614
  throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);
4429
4615
  }
4430
- await fs28.promises.rm(projectDir, { recursive: true, force: true });
4616
+ await fs29.promises.rm(projectDir, { recursive: true, force: true });
4431
4617
  }
4432
4618
  logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);
4433
4619
  await copyDirRecursive(templateDir, projectDir);
4434
4620
  if (moduleName !== defaultModuleName) {
4435
- renameIfExists(path27.join(projectDir, defaultModuleName), path27.join(projectDir, moduleName));
4621
+ renameIfExists(path28.join(projectDir, defaultModuleName), path28.join(projectDir, moduleName));
4436
4622
  }
4437
4623
  updateTemplateConfigs(
4438
4624
  projectDir,
@@ -4449,11 +4635,11 @@ async function createScaffold(opts) {
4449
4635
  }
4450
4636
 
4451
4637
  // src/project/listModules.ts
4452
- var fs29 = __toESM(require("fs"), 1);
4453
- var path28 = __toESM(require("path"), 1);
4638
+ var fs30 = __toESM(require("fs"), 1);
4639
+ var path29 = __toESM(require("path"), 1);
4454
4640
  function listModules(opts) {
4455
- const buildProfile = path28.join(opts.projectDir, "build-profile.json5");
4456
- if (!fs29.existsSync(buildProfile)) {
4641
+ const buildProfile = path29.join(opts.projectDir, "build-profile.json5");
4642
+ if (!fs30.existsSync(buildProfile)) {
4457
4643
  throw new OniroError(`build-profile.json5 not found at ${buildProfile}`);
4458
4644
  }
4459
4645
  const parsed = readJson5File(buildProfile);
@@ -4465,12 +4651,12 @@ function listModules(opts) {
4465
4651
  }
4466
4652
 
4467
4653
  // src/project/abilities.ts
4468
- var fs30 = __toESM(require("fs"), 1);
4469
- var path29 = __toESM(require("path"), 1);
4654
+ var fs31 = __toESM(require("fs"), 1);
4655
+ var path30 = __toESM(require("path"), 1);
4470
4656
  function listAbilities(opts) {
4471
4657
  const moduleName = opts.moduleName ?? "entry";
4472
- const moduleJsonPath = path29.join(opts.projectDir, moduleName, "src", "main", "module.json5");
4473
- if (!fs30.existsSync(moduleJsonPath)) {
4658
+ const moduleJsonPath = path30.join(opts.projectDir, moduleName, "src", "main", "module.json5");
4659
+ if (!fs31.existsSync(moduleJsonPath)) {
4474
4660
  throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
4475
4661
  }
4476
4662
  const parsed = readJson5File(moduleJsonPath);
@@ -4478,12 +4664,12 @@ function listAbilities(opts) {
4478
4664
  }
4479
4665
 
4480
4666
  // src/project/prepareSigning.ts
4481
- var fs31 = __toESM(require("fs"), 1);
4482
- var path30 = __toESM(require("path"), 1);
4667
+ var fs32 = __toESM(require("fs"), 1);
4668
+ var path31 = __toESM(require("path"), 1);
4483
4669
  function hasSigningArtifacts(dir) {
4484
- if (!fs31.existsSync(path30.join(dir, "signatures"))) return false;
4485
- const buildProfile = path30.join(dir, "build-profile.json5");
4486
- if (!fs31.existsSync(buildProfile)) return false;
4670
+ if (!fs32.existsSync(path31.join(dir, "signatures"))) return false;
4671
+ const buildProfile = path31.join(dir, "build-profile.json5");
4672
+ if (!fs32.existsSync(buildProfile)) return false;
4487
4673
  try {
4488
4674
  const parsed = readJson5File(buildProfile);
4489
4675
  return Array.isArray(parsed.app?.signingConfigs) && parsed.app.signingConfigs.length > 0;
@@ -4586,8 +4772,25 @@ async function diffHapAssets(opts) {
4586
4772
  }
4587
4773
 
4588
4774
  // src/install/apply.ts
4589
- var fs32 = __toESM(require("fs"), 1);
4590
- var path31 = __toESM(require("path"), 1);
4775
+ var fs33 = __toESM(require("fs"), 1);
4776
+ var path32 = __toESM(require("path"), 1);
4777
+
4778
+ // src/install/hapBundleName.ts
4779
+ function bundleNameFromHapConfig(text) {
4780
+ try {
4781
+ const parsed = JSON.parse(text.replace(/^/, ""));
4782
+ const name = parsed.app?.bundleName;
4783
+ return typeof name === "string" && name ? name : null;
4784
+ } catch {
4785
+ return null;
4786
+ }
4787
+ }
4788
+ async function readHapBundleName(hapPath) {
4789
+ const config = await readZipEntry(hapPath, (n) => n === "module.json") ?? await readZipEntry(hapPath, (n) => n === "config.json");
4790
+ return config ? bundleNameFromHapConfig(config.toString("utf8")) : null;
4791
+ }
4792
+
4793
+ // src/install/apply.ts
4591
4794
  function decideInstallMethod(s) {
4592
4795
  if (!s.signInfoInconsistent) return "replace";
4593
4796
  if (s.isSystemBundle && !s.allowUninstall) return "refuse";
@@ -4608,7 +4811,7 @@ async function pidOf(config, bundle, deviceSerial) {
4608
4811
  async function resolveHap(opts, logger) {
4609
4812
  let hap;
4610
4813
  if (opts.hapPath) {
4611
- const hapPath = !path31.isAbsolute(opts.hapPath) && opts.projectDir ? path31.join(opts.projectDir, opts.hapPath) : opts.hapPath;
4814
+ const hapPath = !path32.isAbsolute(opts.hapPath) && opts.projectDir ? path32.join(opts.projectDir, opts.hapPath) : opts.hapPath;
4612
4815
  hap = existingHapOrUnsigned(hapPath);
4613
4816
  if (!hap) throw new OniroError(`HAP not found at ${hapPath}.`);
4614
4817
  } else {
@@ -4617,7 +4820,7 @@ async function resolveHap(opts, logger) {
4617
4820
  if (!picked) throw new OniroError(`No HAP found${opts.module ? ` for module ${opts.module}` : ""}. Build first.`);
4618
4821
  hap = { path: picked.path, fallback: !picked.signed };
4619
4822
  }
4620
- if (hap.fallback) logger.warn(`No signed HAP found; installing the unsigned ${path31.basename(hap.path)}.`);
4823
+ if (hap.fallback) logger.warn(`No signed HAP found; installing the unsigned ${path32.basename(hap.path)}.`);
4621
4824
  return hap;
4622
4825
  }
4623
4826
  async function applyChanges(opts) {
@@ -4627,9 +4830,18 @@ async function applyChanges(opts) {
4627
4830
  const allowUninstall = opts.allowUninstall ?? false;
4628
4831
  const hap = await resolveHap(opts, logger);
4629
4832
  const hapPath = hap.path;
4833
+ const hapBundle = await readHapBundleName(hapPath).catch((err) => {
4834
+ logger.debug(`bundle name check skipped: ${err.message}`);
4835
+ return null;
4836
+ });
4837
+ if (hapBundle && hapBundle !== bundle) {
4838
+ throw new OniroError(
4839
+ `${path32.basename(hapPath)} (${hapPath}) is bundle ${hapBundle}, not ${bundle}, so installing it would not update ${bundle}. Choose the HAP explicitly, or name ${hapBundle} as the bundle if it is the app to update.`
4840
+ );
4841
+ }
4630
4842
  logger.info(`installing ${hapPath}`);
4631
4843
  let assetsChanged = false;
4632
- if (opts.installedHapPath && fs32.existsSync(opts.installedHapPath)) {
4844
+ if (opts.installedHapPath && fs33.existsSync(opts.installedHapPath)) {
4633
4845
  try {
4634
4846
  const diff = await diffHapAssets({ installedHap: opts.installedHapPath, newHap: hapPath });
4635
4847
  assetsChanged = diff.addedAssetPaths.length > 0 || diff.removedAssetPaths.length > 0;
@@ -4662,7 +4874,7 @@ async function applyChanges(opts) {
4662
4874
  }
4663
4875
  if (!await isBundleInstalled({ config, bundle, deviceSerial })) {
4664
4876
  throw new OniroError(
4665
- `hdc reported ${path31.basename(hapPath)} as installed, but bm dump does not list ${bundle}. Check that the HAP was built from this project (its bundleName must match).`
4877
+ `hdc reported ${path32.basename(hapPath)} as installed, but bm dump does not list ${bundle}. Check that the HAP was built from this project (its bundleName must match).`
4666
4878
  );
4667
4879
  }
4668
4880
  let postInstallPid = await pidOf(config, bundle, deviceSerial);
@@ -4739,9 +4951,9 @@ var AUTH_PATHS = {
4739
4951
  };
4740
4952
 
4741
4953
  // src/harmonyos/auth/tokenStore.ts
4742
- var fs33 = __toESM(require("fs"), 1);
4954
+ var fs34 = __toESM(require("fs"), 1);
4743
4955
  var os11 = __toESM(require("os"), 1);
4744
- var path32 = __toESM(require("path"), 1);
4956
+ var path33 = __toESM(require("path"), 1);
4745
4957
  var crypto3 = __toESM(require("crypto"), 1);
4746
4958
  var ALGORITHM = "aes-256-gcm";
4747
4959
  var KEY_LENGTH = 32;
@@ -4777,7 +4989,7 @@ function permissionHint(dir) {
4777
4989
  }
4778
4990
  function ensureDir(dir) {
4779
4991
  try {
4780
- fs33.mkdirSync(dir, { recursive: true, mode: DIR_MODE });
4992
+ fs34.mkdirSync(dir, { recursive: true, mode: DIR_MODE });
4781
4993
  } catch (err) {
4782
4994
  if (err.code === "EACCES") {
4783
4995
  throw new OniroError(permissionHint(dir), err);
@@ -4788,17 +5000,17 @@ function ensureDir(dir) {
4788
5000
  function createTokenStore(opts) {
4789
5001
  const logger = opts.logger ?? noopLogger;
4790
5002
  const authDir = opts.config.get("harmonyosAuthDir", defaultPaths.harmonyosAuthDir());
4791
- const tokenPath = path32.join(authDir, TOKEN_FILE);
4792
- const keyPath = path32.join(os11.homedir(), ".local", "share", "oniro-app", "keys", KEY_FILE);
5003
+ const tokenPath = path33.join(authDir, TOKEN_FILE);
5004
+ const keyPath = path33.join(os11.homedir(), ".local", "share", "oniro-app", "keys", KEY_FILE);
4793
5005
  function loadOrCreateKey() {
4794
- if (fs33.existsSync(keyPath)) {
4795
- const existing = fs33.readFileSync(keyPath);
5006
+ if (fs34.existsSync(keyPath)) {
5007
+ const existing = fs34.readFileSync(keyPath);
4796
5008
  if (existing.length === KEY_LENGTH) return existing;
4797
5009
  logger.warn("[harmonyos] The token key file was malformed; regenerating (you will need to log in again).");
4798
5010
  }
4799
- ensureDir(path32.dirname(keyPath));
5011
+ ensureDir(path33.dirname(keyPath));
4800
5012
  const key = crypto3.randomBytes(KEY_LENGTH);
4801
- fs33.writeFileSync(keyPath, key, { mode: FILE_MODE });
5013
+ fs34.writeFileSync(keyPath, key, { mode: FILE_MODE });
4802
5014
  return key;
4803
5015
  }
4804
5016
  return {
@@ -4808,12 +5020,12 @@ function createTokenStore(opts) {
4808
5020
  const payload = Buffer.from(JSON.stringify(session), "utf8");
4809
5021
  const blob = encrypt2(loadOrCreateKey(), payload);
4810
5022
  ensureDir(authDir);
4811
- fs33.writeFileSync(tokenPath, JSON.stringify(blob, null, 2), { mode: FILE_MODE });
5023
+ fs34.writeFileSync(tokenPath, JSON.stringify(blob, null, 2), { mode: FILE_MODE });
4812
5024
  },
4813
5025
  load() {
4814
- if (!fs33.existsSync(tokenPath)) return null;
5026
+ if (!fs34.existsSync(tokenPath)) return null;
4815
5027
  try {
4816
- const blob = JSON.parse(fs33.readFileSync(tokenPath, "utf8"));
5028
+ const blob = JSON.parse(fs34.readFileSync(tokenPath, "utf8"));
4817
5029
  if (!isEncryptedBlob(blob)) return null;
4818
5030
  const { jwtToken, siteId } = JSON.parse(decrypt2(loadOrCreateKey(), blob).toString("utf8"));
4819
5031
  return typeof jwtToken === "string" && jwtToken && typeof siteId === "string" ? { jwtToken, siteId } : null;
@@ -4825,7 +5037,7 @@ function createTokenStore(opts) {
4825
5037
  }
4826
5038
  logger.debug(`[harmonyos] Discarding unreadable token at ${tokenPath}.`);
4827
5039
  try {
4828
- fs33.rmSync(tokenPath, { force: true });
5040
+ fs34.rmSync(tokenPath, { force: true });
4829
5041
  } catch {
4830
5042
  }
4831
5043
  return null;
@@ -4833,7 +5045,7 @@ function createTokenStore(opts) {
4833
5045
  },
4834
5046
  clear() {
4835
5047
  try {
4836
- fs33.rmSync(tokenPath, { force: true });
5048
+ fs34.rmSync(tokenPath, { force: true });
4837
5049
  } catch (err) {
4838
5050
  throw new OniroError(`Failed to remove ${tokenPath}.`, err);
4839
5051
  }
@@ -5269,7 +5481,7 @@ var SIGNING_ERRORS = {
5269
5481
  DEVICE_ADD: "AppGallery Connect did not register the device.",
5270
5482
  DEVICE_LIMIT: "This team has reached its device limit. Remove an unused device in AppGallery Connect and retry.",
5271
5483
  DEVICE_NAME_REPEAT: "A device with that name is already registered. Retry.",
5272
- DEVICE_NONE: "No device is connected and none is registered to this team, but a debug profile must name at least one. Connect a device and retry.",
5484
+ DEVICE_NONE: "This team has no registered device and none could be registered from here, but a debug profile must name at least one. Connect a device that reports a UDID (`hdc shell bm get -u`), or register one in AppGallery Connect, and retry.",
5273
5485
  PROFILE_ADD: "AppGallery Connect did not issue the provisioning profile.",
5274
5486
  PROFILE_NAME_REPEAT: "A provisioning profile with that name already exists in AppGallery Connect. Retry.",
5275
5487
  PROVISION_LIMIT: "This team has reached its debug-profile limit. Delete unused profiles in AppGallery Connect and retry.",
@@ -5314,7 +5526,7 @@ function mapAgcError(operation, statusCode, reasonPhrase, body) {
5314
5526
  }
5315
5527
 
5316
5528
  // src/harmonyos/signing/profile.ts
5317
- var fs34 = __toESM(require("fs"), 1);
5529
+ var fs35 = __toESM(require("fs"), 1);
5318
5530
  var import_node_crypto3 = require("crypto");
5319
5531
  var import_node_forge = __toESM(require("node-forge"), 1);
5320
5532
  function extractProfileJson(buffer) {
@@ -5346,7 +5558,7 @@ function extractProfileJson(buffer) {
5346
5558
  function readProvisionProfile(profilePath) {
5347
5559
  let raw;
5348
5560
  try {
5349
- const json = extractProfileJson(fs34.readFileSync(profilePath));
5561
+ const json = extractProfileJson(fs35.readFileSync(profilePath));
5350
5562
  if (!json) return null;
5351
5563
  raw = JSON.parse(json);
5352
5564
  } catch {
@@ -5375,7 +5587,7 @@ function parseCertificate(pem) {
5375
5587
  }
5376
5588
  function keystoreHoldsKey(p12Path, keyAlias, keyPwd, certificate) {
5377
5589
  try {
5378
- const der = import_node_forge.default.util.createBuffer(fs34.readFileSync(p12Path).toString("binary"));
5590
+ const der = import_node_forge.default.util.createBuffer(fs35.readFileSync(p12Path).toString("binary"));
5379
5591
  const p12 = import_node_forge.default.pkcs12.pkcs12FromAsn1(import_node_forge.default.asn1.fromDer(der), keyPwd);
5380
5592
  const certBag = import_node_forge.default.pki.oids.certBag ?? "1.2.840.113549.1.12.10.1.3";
5381
5593
  const wanted = certificate.publicKey.export({ type: "spki", format: "der" });
@@ -5391,7 +5603,7 @@ function keystoreHoldsKey(p12Path, keyAlias, keyPwd, certificate) {
5391
5603
  }
5392
5604
  }
5393
5605
  function verifySigningMaterial(opts) {
5394
- const pems = fs34.readFileSync(opts.cerPath, "utf8").match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g);
5606
+ const pems = fs35.readFileSync(opts.cerPath, "utf8").match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g);
5395
5607
  const chain = (pems ?? []).map(parseCertificate);
5396
5608
  const leaf = chain.find((c) => !c.ca) ?? chain.at(-1);
5397
5609
  if (!leaf) throw new AgcError(SIGNING_ERRORS.CERT_INVALID);
@@ -5410,14 +5622,14 @@ function verifySigningMaterial(opts) {
5410
5622
 
5411
5623
  // src/harmonyos/signing/autoSign.ts
5412
5624
  var crypto9 = __toESM(require("crypto"), 1);
5413
- var fs39 = __toESM(require("fs"), 1);
5414
- var path38 = __toESM(require("path"), 1);
5625
+ var fs40 = __toESM(require("fs"), 1);
5626
+ var path39 = __toESM(require("path"), 1);
5415
5627
  var import_json57 = __toESM(require("json5"), 1);
5416
5628
 
5417
5629
  // src/harmonyos/signing/agc.ts
5418
5630
  var crypto6 = __toESM(require("crypto"), 1);
5419
- var fs35 = __toESM(require("fs"), 1);
5420
- var path33 = __toESM(require("path"), 1);
5631
+ var fs36 = __toESM(require("fs"), 1);
5632
+ var path34 = __toESM(require("path"), 1);
5421
5633
  var ENDPOINTS = {
5422
5634
  CERT_LIST: "/api/cps/harmony-cert-manage/v1/cert/list",
5423
5635
  CERT_ADD: "/api/cps/harmony-cert-manage/v1/cert/add",
@@ -5503,8 +5715,8 @@ function createAgcClient(http3, auth) {
5503
5715
  if (target.sha256 && actual !== target.sha256.toLowerCase()) {
5504
5716
  throw new ChecksumMismatchError(target.sha256, actual);
5505
5717
  }
5506
- fs35.mkdirSync(path33.dirname(dest), { recursive: true, mode: 448 });
5507
- fs35.writeFileSync(dest, buffer, { mode: 384 });
5718
+ fs36.mkdirSync(path34.dirname(dest), { recursive: true, mode: 448 });
5719
+ fs36.writeFileSync(dest, buffer, { mode: 384 });
5508
5720
  }
5509
5721
  };
5510
5722
  }
@@ -5518,21 +5730,31 @@ function parseDeviceKind(stdout) {
5518
5730
  }
5519
5731
  async function collectLocalDevices(config, logger) {
5520
5732
  const devices = [];
5733
+ const skipped = [];
5521
5734
  for (const target of await listDevices(config, { logger, timeoutMs: 15e3 })) {
5522
- if (target.status !== "Connected") continue;
5735
+ const skip = (why) => {
5736
+ logger.warn(`[harmonyos] ${target.serial} ${why}`);
5737
+ skipped.push(target.serial);
5738
+ };
5739
+ if (!isUsableDevice(target)) {
5740
+ skip(
5741
+ target.status === "Unauthorized" ? "is unauthorized; accept the debugging prompt on the device to register it." : `is ${target.status.toLowerCase()}; skipping it.`
5742
+ );
5743
+ continue;
5744
+ }
5523
5745
  const shell2 = async (...args) => (await hdcExec({ config, deviceSerial: target.serial, args: ["shell", ...args], timeoutMs: 15e3, logger })).stdout;
5524
5746
  try {
5525
5747
  const udid = parseUdid(await shell2("bm", "get", "-u"));
5526
5748
  if (!udid) {
5527
- logger.warn(`[harmonyos] ${target.serial} did not report a UDID; skipping it.`);
5749
+ skip("did not report a UDID (`bm get -u`), so it cannot be registered.");
5528
5750
  continue;
5529
5751
  }
5530
5752
  devices.push({ serial: target.serial, udid, kind: parseDeviceKind(await shell2("getprop", "hw_sc.build.os.deviceType")) });
5531
5753
  } catch (err) {
5532
- logger.warn(`[harmonyos] Could not read ${target.serial}: ${err.message}`);
5754
+ skip(`could not be read: ${err.message}`);
5533
5755
  }
5534
5756
  }
5535
- return devices;
5757
+ return { devices, skipped };
5536
5758
  }
5537
5759
  async function registerDevices(agc, connected, logger) {
5538
5760
  let devices = await agc.listDevices();
@@ -5545,32 +5767,27 @@ async function registerDevices(agc, connected, logger) {
5545
5767
  if (unregistered.length > 0) devices = await agc.listDevices();
5546
5768
  const deviceIds = devices.map((d) => d.id);
5547
5769
  if (deviceIds.length === 0) throw new AgcError(SIGNING_ERRORS.DEVICE_NONE);
5548
- if (connected.length === 0) {
5549
- logger.warn(
5550
- `[harmonyos] No device is connected; the profile will name the ${deviceIds.length} device(s) already registered to this team.`
5551
- );
5552
- }
5553
5770
  return deviceIds;
5554
5771
  }
5555
5772
 
5556
5773
  // src/harmonyos/signing/keystore.ts
5557
5774
  var crypto7 = __toESM(require("crypto"), 1);
5558
- var fs37 = __toESM(require("fs"), 1);
5559
- var path35 = __toESM(require("path"), 1);
5775
+ var fs38 = __toESM(require("fs"), 1);
5776
+ var path36 = __toESM(require("path"), 1);
5560
5777
 
5561
5778
  // src/harmonyos/java.ts
5562
- var fs36 = __toESM(require("fs"), 1);
5563
- var path34 = __toESM(require("path"), 1);
5779
+ var fs37 = __toESM(require("fs"), 1);
5780
+ var path35 = __toESM(require("path"), 1);
5564
5781
  var JAVA_BIN = process.platform === "win32" ? "java.exe" : "java";
5565
5782
  function findJava(sdk, env = process.env) {
5566
5783
  const candidates = [
5567
- env.JAVA_HOME && path34.join(env.JAVA_HOME, "bin", JAVA_BIN),
5568
- sdk && path34.join(sdk.installRoot, "jbr", "bin", JAVA_BIN),
5784
+ env.JAVA_HOME && path35.join(env.JAVA_HOME, "bin", JAVA_BIN),
5785
+ sdk && path35.join(sdk.installRoot, "jbr", "bin", JAVA_BIN),
5569
5786
  // macOS: the JBR is itself a bundle inside Studio's Contents.
5570
- sdk && path34.join(sdk.installRoot, "jbr", "Contents", "Home", "bin", JAVA_BIN),
5571
- ...(env.PATH ?? "").split(path34.delimiter).map((dir) => dir && path34.join(dir, JAVA_BIN))
5787
+ sdk && path35.join(sdk.installRoot, "jbr", "Contents", "Home", "bin", JAVA_BIN),
5788
+ ...(env.PATH ?? "").split(path35.delimiter).map((dir) => dir && path35.join(dir, JAVA_BIN))
5572
5789
  ];
5573
- const found = candidates.find((c) => !!c && fs36.existsSync(c));
5790
+ const found = candidates.find((c) => !!c && fs37.existsSync(c));
5574
5791
  if (found) return found;
5575
5792
  throw new OniroError(
5576
5793
  "No Java runtime found. HarmonyOS signing runs the SDK's hap-sign-tool.jar, which needs one: install a JDK and set JAVA_HOME, or install DevEco Studio, whose bundled runtime is used automatically."
@@ -5584,13 +5801,13 @@ function redactArgs(args) {
5584
5801
  return args.map((arg, i) => args[i - 1] === "-keyPwd" || args[i - 1] === "-keystorePwd" ? "******" : arg);
5585
5802
  }
5586
5803
  async function generateKeystoreAndCsr(opts) {
5587
- const jar = path35.join(opts.sdk.sdkPath, "default", "openharmony", "toolchains", "lib", "hap-sign-tool.jar");
5588
- if (!fs37.existsSync(jar)) {
5804
+ const jar = path36.join(opts.sdk.sdkPath, "default", "openharmony", "toolchains", "lib", "hap-sign-tool.jar");
5805
+ if (!fs38.existsSync(jar)) {
5589
5806
  throw new OniroError(`hap-sign-tool.jar not found at ${jar}; the HarmonyOS SDK looks incomplete.`);
5590
5807
  }
5591
5808
  const java = findJava(opts.sdk);
5592
5809
  const keyPwd = crypto7.randomBytes(12).toString("base64url").replaceAll(/[-_]/g, "");
5593
- fs37.mkdirSync(path35.dirname(opts.p12Path), { recursive: true, mode: 448 });
5810
+ fs38.mkdirSync(path36.dirname(opts.p12Path), { recursive: true, mode: 448 });
5594
5811
  const run = async (what, args) => {
5595
5812
  const argv = ["-jar", jar, ...args, "-keyAlias", KEY_ALIAS, "-keystoreFile", opts.p12Path, "-keystorePwd", keyPwd, "-keyPwd", keyPwd];
5596
5813
  opts.logger.debug(`[harmonyos] ${java} ${redactArgs(argv).join(" ")}`);
@@ -5604,28 +5821,28 @@ ${detail}` : ""}`);
5604
5821
  opts.logger.info("[harmonyos] Generating the local keystore and certificate signing request...");
5605
5822
  await run("generate the key pair", ["generate-keypair", "-keyAlg", "ECC", "-keySize", "NIST-P-256"]);
5606
5823
  await run("generate the CSR", ["generate-csr", "-subject", "CN=DebugKey", "-signAlg", SIGN_ALG, "-outFile", opts.csrPath]);
5607
- return { keyPwd, csr: fs37.readFileSync(opts.csrPath, "utf8") };
5824
+ return { keyPwd, csr: fs38.readFileSync(opts.csrPath, "utf8") };
5608
5825
  }
5609
5826
 
5610
5827
  // src/harmonyos/signing/paths.ts
5611
5828
  var crypto8 = __toESM(require("crypto"), 1);
5612
- var path36 = __toESM(require("path"), 1);
5829
+ var path37 = __toESM(require("path"), 1);
5613
5830
  function sanitizeNamePart(raw) {
5614
5831
  const safe = (raw?.trim() ?? "").replace(/[\\/:*?"<>|=.-]+/g, "_");
5615
5832
  return safe.slice(0, 64) || "default";
5616
5833
  }
5617
5834
  function resolveSigningMaterialPaths(config, productName, projectRoot) {
5618
5835
  const hash = crypto8.createHash("sha256").update(projectRoot, "utf8").digest("base64url").replaceAll(/[-_]/g, "");
5619
- const base = path36.join(
5836
+ const base = path37.join(
5620
5837
  config.get("harmonyosSigningDir", defaultPaths.harmonyosSigningDir()),
5621
- `${sanitizeNamePart(productName)}_${path36.basename(projectRoot)}_${hash}=`
5838
+ `${sanitizeNamePart(productName)}_${path37.basename(projectRoot)}_${hash}=`
5622
5839
  );
5623
5840
  return { p12Path: `${base}.p12`, csrPath: `${base}.csr`, cerPath: `${base}.cer`, profilePath: `${base}.p7b` };
5624
5841
  }
5625
5842
 
5626
5843
  // src/harmonyos/signing/project.ts
5627
- var fs38 = __toESM(require("fs"), 1);
5628
- var path37 = __toESM(require("path"), 1);
5844
+ var fs39 = __toESM(require("fs"), 1);
5845
+ var path38 = __toESM(require("path"), 1);
5629
5846
  var import_json56 = __toESM(require("json5"), 1);
5630
5847
 
5631
5848
  // src/harmonyos/signing/aclPermissionList.ts
@@ -5693,9 +5910,9 @@ var ACL_PERMISSIONS = /* @__PURE__ */ new Set([
5693
5910
 
5694
5911
  // src/harmonyos/signing/project.ts
5695
5912
  function readRequestedPermissions(moduleConfigPath) {
5696
- if (!fs38.existsSync(moduleConfigPath)) return [];
5913
+ if (!fs39.existsSync(moduleConfigPath)) return [];
5697
5914
  try {
5698
- const parsed = import_json56.default.parse(fs38.readFileSync(moduleConfigPath, "utf-8"));
5915
+ const parsed = import_json56.default.parse(fs39.readFileSync(moduleConfigPath, "utf-8"));
5699
5916
  return (parsed.module?.requestPermissions ?? []).map((p) => p?.name).filter((n) => typeof n === "string" && n.length > 0);
5700
5917
  } catch {
5701
5918
  return [];
@@ -5704,10 +5921,10 @@ function readRequestedPermissions(moduleConfigPath) {
5704
5921
  function collectAclPermissions(projectDir, logger = noopLogger) {
5705
5922
  const requested = /* @__PURE__ */ new Set();
5706
5923
  for (const module2 of listModules({ projectDir })) {
5707
- const moduleRoot = path37.resolve(projectDir, module2.srcPath);
5924
+ const moduleRoot = path38.resolve(projectDir, module2.srcPath);
5708
5925
  for (const sourceSet of ["main", "ohosTest"]) {
5709
5926
  for (const name of readRequestedPermissions(
5710
- path37.join(moduleRoot, "src", sourceSet, "module.json5")
5927
+ path38.join(moduleRoot, "src", sourceSet, "module.json5")
5711
5928
  )) {
5712
5929
  requested.add(name);
5713
5930
  }
@@ -5723,7 +5940,7 @@ function collectAclPermissions(projectDir, logger = noopLogger) {
5723
5940
  // src/harmonyos/signing/autoSign.ts
5724
5941
  function shouldRegenerate(input) {
5725
5942
  if (input.force) return "--force was passed";
5726
- const missing = Object.values(input.paths).find((file) => !fs39.existsSync(file));
5943
+ const missing = Object.values(input.paths).find((file) => !fs40.existsSync(file));
5727
5944
  if (missing) return `${missing} is missing`;
5728
5945
  const config = input.buildProfile.app?.signingConfigs?.find((c) => c.name === input.productName);
5729
5946
  if (config?.type !== "HarmonyOS" || config.material?.profile !== input.paths.profilePath) {
@@ -5762,16 +5979,16 @@ function writeSigningConfig(opts) {
5762
5979
  for (const product of app.products ?? []) {
5763
5980
  if (product.name === opts.productName) product.signingConfig = opts.productName;
5764
5981
  }
5765
- fs39.writeFileSync(opts.buildProfilePath, JSON.stringify(opts.buildProfile, null, 2));
5982
+ fs40.writeFileSync(opts.buildProfilePath, JSON.stringify(opts.buildProfile, null, 2));
5766
5983
  }
5767
5984
  async function harmonyOsAutoSign(opts) {
5768
5985
  const logger = opts.logger ?? noopLogger;
5769
5986
  const productName = opts.productName ?? "default";
5770
- const projectDir = path38.resolve(opts.projectDir);
5771
- const buildProfilePath = path38.join(projectDir, "build-profile.json5");
5987
+ const projectDir = path39.resolve(opts.projectDir);
5988
+ const buildProfilePath = path39.join(projectDir, "build-profile.json5");
5772
5989
  let buildProfile;
5773
5990
  try {
5774
- buildProfile = import_json57.default.parse(fs39.readFileSync(buildProfilePath, "utf-8"));
5991
+ buildProfile = import_json57.default.parse(fs40.readFileSync(buildProfilePath, "utf-8"));
5775
5992
  } catch (err) {
5776
5993
  throw new OniroError(`Could not read ${buildProfilePath}: ${err.message}`, err);
5777
5994
  }
@@ -5786,7 +6003,7 @@ async function harmonyOsAutoSign(opts) {
5786
6003
  const aclPermissions = collectAclPermissions(projectDir, logger);
5787
6004
  const paths = resolveSigningMaterialPaths(opts.config, productName, projectDir);
5788
6005
  logger.info(`[harmonyos] Signing ${bundleName} (product '${productName}', team ${auth.teamId}).`);
5789
- const connected = await collectLocalDevices(opts.config, logger);
6006
+ const local = await collectLocalDevices(opts.config, logger);
5790
6007
  const result = (regenerated) => ({
5791
6008
  bundleName,
5792
6009
  teamId: auth.teamId,
@@ -5800,7 +6017,7 @@ async function harmonyOsAutoSign(opts) {
5800
6017
  productName,
5801
6018
  bundleName,
5802
6019
  teamId: auth.teamId,
5803
- connectedUdids: connected.map((d) => d.udid),
6020
+ connectedUdids: local.devices.map((d) => d.udid),
5804
6021
  aclPermissions,
5805
6022
  force: opts.force
5806
6023
  });
@@ -5810,8 +6027,12 @@ async function harmonyOsAutoSign(opts) {
5810
6027
  }
5811
6028
  logger.info(`[harmonyos] Regenerating signing material: ${reason}.`);
5812
6029
  const agc = createAgcClient(opts.http ?? createHttpClient({ logger }), auth);
5813
- const deviceIds = await registerDevices(agc, connected, logger);
5814
- for (const file of Object.values(paths)) fs39.rmSync(file, { force: true });
6030
+ const deviceIds = await registerDevices(agc, local.devices, logger);
6031
+ if (local.devices.length === 0) {
6032
+ const cause = local.skipped.length > 0 ? "No connected device could be registered" : "No device is connected";
6033
+ logger.warn(`[harmonyos] ${cause}; the profile will name the ${deviceIds.length} device(s) already registered to this team.`);
6034
+ }
6035
+ for (const file of Object.values(paths)) fs40.rmSync(file, { force: true });
5815
6036
  const certName = `oniro_debug_${auth.teamId.replace(/[\\/.:]/g, "")}.cer`;
5816
6037
  const stale = (await agc.listCertificates()).find((c) => c.certName === certName);
5817
6038
  if (stale) {
@@ -5842,10 +6063,10 @@ async function harmonyOsAutoSign(opts) {
5842
6063
  try {
5843
6064
  verifySigningMaterial({ ...paths, keyAlias: KEY_ALIAS, keyPwd });
5844
6065
  } catch (err) {
5845
- fs39.rmSync(paths.profilePath, { force: true });
6066
+ fs40.rmSync(paths.profilePath, { force: true });
5846
6067
  throw err;
5847
6068
  }
5848
- const materialDir = path38.join(path38.dirname(paths.p12Path), "material");
6069
+ const materialDir = path39.join(path39.dirname(paths.p12Path), "material");
5849
6070
  try {
5850
6071
  getKey(materialDir);
5851
6072
  } catch {
@@ -5857,7 +6078,7 @@ async function harmonyOsAutoSign(opts) {
5857
6078
  }
5858
6079
 
5859
6080
  // src/index.ts
5860
- var VERSION = "0.14.1";
6081
+ var VERSION = "0.15.1";
5861
6082
  // Annotate the CommonJS export names for ESM import in node:
5862
6083
  0 && (module.exports = {
5863
6084
  ALL_SDKS,
@@ -5872,6 +6093,7 @@ var VERSION = "0.14.1";
5872
6093
  HUAWEI_SITES,
5873
6094
  INSTALL_TMP_DIRNAME,
5874
6095
  InsufficientSpaceError,
6096
+ OHOS_DAILY_BUILDS_URL,
5875
6097
  OHOS_URL_BASE,
5876
6098
  OniroError,
5877
6099
  SIGNING_ERRORS,
@@ -5892,6 +6114,7 @@ var VERSION = "0.14.1";
5892
6114
  buildHvigorwArgs,
5893
6115
  buildInputCommand,
5894
6116
  buildRawTouchCommand,
6117
+ bundleNameFromHapConfig,
5895
6118
  captureBurst,
5896
6119
  captureLog,
5897
6120
  cleanCodelinterOutput,
@@ -5945,6 +6168,7 @@ var VERSION = "0.14.1";
5945
6168
  findLayoutNodes,
5946
6169
  findMissingProjectSdk,
5947
6170
  findRunningProcess,
6171
+ findSdkOsDir,
5948
6172
  flattenLayout,
5949
6173
  forceStop,
5950
6174
  formatBytes,
@@ -5978,16 +6202,19 @@ var VERSION = "0.14.1";
5978
6202
  hdcTargetArgs,
5979
6203
  hdcTargetArgsFor,
5980
6204
  hideKeyboard,
6205
+ hilogTimeMs,
5981
6206
  installApp,
5982
6207
  installCmdTools,
5983
6208
  installEmulator,
5984
6209
  installFailureReason,
6210
+ installSdkFromArchive,
5985
6211
  isBundleInstalled,
5986
6212
  isCmdToolsInstalled,
5987
6213
  isEmulatorInstalled,
5988
6214
  isOutOfSpaceError,
5989
6215
  isRamBackedPath,
5990
6216
  isUnsignedHap,
6217
+ isUsableDevice,
5991
6218
  isValidBundleName,
5992
6219
  isValidProjectName,
5993
6220
  killProcessTree,
@@ -5998,6 +6225,7 @@ var VERSION = "0.14.1";
5998
6225
  listRunningProcesses,
5999
6226
  listTemplates,
6000
6227
  locateTarget,
6228
+ missingProjectRootFiles,
6001
6229
  needsCmdWrapper,
6002
6230
  nonInteractivePrompter,
6003
6231
  noopLogger,
@@ -6021,9 +6249,11 @@ var VERSION = "0.14.1";
6021
6249
  pickTarget,
6022
6250
  prepareSigning,
6023
6251
  pruneLayout,
6252
+ readHapBundleName,
6024
6253
  readJson5File,
6025
6254
  readJsonFile,
6026
6255
  readProvisionProfile,
6256
+ readZipEntry,
6027
6257
  reboot,
6028
6258
  recvFile,
6029
6259
  removeCmdTools,