@oniroproject/core 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.cjs +388 -160
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +98 -13
- package/dist/index.d.ts +98 -13
- package/dist/index.js +380 -160
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -180,6 +180,7 @@ var ALL_SDKS = [
|
|
|
180
180
|
{ version: "7.0", api: "26", tarballStrip: { linuxWindows: 1, darwin: 3 }, archiveSuffix: "_20260829" }
|
|
181
181
|
];
|
|
182
182
|
var OHOS_URL_BASE = "https://repo.huaweicloud.com/openharmony/os";
|
|
183
|
+
var OHOS_DAILY_BUILDS_URL = "https://dcp.openharmony.cn/workbench/cicd/dailybuild/dailylist";
|
|
183
184
|
|
|
184
185
|
// src/sdk/platform.ts
|
|
185
186
|
import * as os2 from "os";
|
|
@@ -762,8 +763,17 @@ async function extractZipWithProgress(opts) {
|
|
|
762
763
|
if (inc > 0) progress.report({ message: "Extracting: 100%", increment: inc });
|
|
763
764
|
}
|
|
764
765
|
}
|
|
765
|
-
async function extractTarball(tarPath, dest, strip = 0) {
|
|
766
|
-
await tar.x({ file: tarPath, cwd: dest, strip });
|
|
766
|
+
async function extractTarball(tarPath, dest, strip = 0, filter) {
|
|
767
|
+
await tar.x({ file: tarPath, cwd: dest, strip, ...filter ? { filter: (p) => filter(p) } : {} });
|
|
768
|
+
}
|
|
769
|
+
async function readZipEntry(zipPath, match) {
|
|
770
|
+
const zip = new StreamZip.async({ file: zipPath });
|
|
771
|
+
try {
|
|
772
|
+
const entry = Object.values(await zip.entries()).find((e) => !e.isDirectory && match(e.name));
|
|
773
|
+
return entry ? await zip.entryData(entry) : void 0;
|
|
774
|
+
} finally {
|
|
775
|
+
await zip.close();
|
|
776
|
+
}
|
|
767
777
|
}
|
|
768
778
|
|
|
769
779
|
// src/sdk/list.ts
|
|
@@ -869,34 +879,7 @@ async function downloadAndInstallSdk(opts) {
|
|
|
869
879
|
`Expected folder '${osFolder}' not found in extracted SDK. Tarball layout may have changed.`
|
|
870
880
|
);
|
|
871
881
|
}
|
|
872
|
-
|
|
873
|
-
const componentsStart = 60;
|
|
874
|
-
const componentsBudget = 35;
|
|
875
|
-
const n = zipFiles.length;
|
|
876
|
-
if (n === 0) {
|
|
877
|
-
progress?.report({ message: "No SDK component ZIPs found.", increment: componentsBudget });
|
|
878
|
-
} else {
|
|
879
|
-
progress?.report({ message: "Extracting SDK components...", increment: 0 });
|
|
880
|
-
}
|
|
881
|
-
const base = n > 0 ? Math.floor(componentsBudget / n) : 0;
|
|
882
|
-
let rem = n > 0 ? componentsBudget % n : 0;
|
|
883
|
-
let cursor = componentsStart;
|
|
884
|
-
for (const zipFile of zipFiles) {
|
|
885
|
-
checkCancelled();
|
|
886
|
-
logger.info(`Extracting component ${zipFile}`);
|
|
887
|
-
const zipPath = path10.join(osContentPath, zipFile);
|
|
888
|
-
const thisBudget = base + (rem > 0 ? 1 : 0);
|
|
889
|
-
if (rem > 0) rem--;
|
|
890
|
-
await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });
|
|
891
|
-
cursor += thisBudget;
|
|
892
|
-
fs10.unlinkSync(zipPath);
|
|
893
|
-
}
|
|
894
|
-
progress?.report({ message: "Finalizing installation...", increment: 0 });
|
|
895
|
-
if (fs10.existsSync(sdkInstallDir)) {
|
|
896
|
-
fs10.rmSync(sdkInstallDir, { recursive: true, force: true });
|
|
897
|
-
}
|
|
898
|
-
movePath(osContentPath, sdkInstallDir);
|
|
899
|
-
progress?.report({ message: "Finalizing installation...", increment: 3 });
|
|
882
|
+
await installComponents({ osContentPath, sdkInstallDir, progress, logger, start: 60, range: 35, checkCancelled });
|
|
900
883
|
progress?.report({ message: "Cleaning up...", increment: 0 });
|
|
901
884
|
removeTempWorkDir(tmpDir, tmpRoot);
|
|
902
885
|
progress?.report({ message: "Cleaning up...", increment: 2 });
|
|
@@ -907,6 +890,115 @@ async function downloadAndInstallSdk(opts) {
|
|
|
907
890
|
throw wrapped;
|
|
908
891
|
}
|
|
909
892
|
}
|
|
893
|
+
async function installComponents(opts) {
|
|
894
|
+
const { osContentPath, sdkInstallDir, progress, logger, checkCancelled } = opts;
|
|
895
|
+
const zipFiles = fs10.readdirSync(osContentPath).filter((n2) => n2.endsWith(".zip"));
|
|
896
|
+
const n = zipFiles.length;
|
|
897
|
+
if (n === 0) {
|
|
898
|
+
progress?.report({ message: "No SDK component ZIPs found.", increment: opts.range });
|
|
899
|
+
} else {
|
|
900
|
+
progress?.report({ message: "Extracting SDK components...", increment: 0 });
|
|
901
|
+
}
|
|
902
|
+
const base = n > 0 ? Math.floor(opts.range / n) : 0;
|
|
903
|
+
let rem = n > 0 ? opts.range % n : 0;
|
|
904
|
+
let cursor = opts.start;
|
|
905
|
+
for (const zipFile of zipFiles) {
|
|
906
|
+
checkCancelled();
|
|
907
|
+
logger.info(`Extracting component ${zipFile}`);
|
|
908
|
+
const zipPath = path10.join(osContentPath, zipFile);
|
|
909
|
+
const thisBudget = base + (rem > 0 ? 1 : 0);
|
|
910
|
+
if (rem > 0) rem--;
|
|
911
|
+
await extractZipWithProgress({ zipPath, dest: osContentPath, progress, start: cursor, range: thisBudget, logger });
|
|
912
|
+
cursor += thisBudget;
|
|
913
|
+
fs10.unlinkSync(zipPath);
|
|
914
|
+
}
|
|
915
|
+
progress?.report({ message: "Finalizing installation...", increment: 0 });
|
|
916
|
+
if (fs10.existsSync(sdkInstallDir)) {
|
|
917
|
+
fs10.rmSync(sdkInstallDir, { recursive: true, force: true });
|
|
918
|
+
}
|
|
919
|
+
movePath(osContentPath, sdkInstallDir);
|
|
920
|
+
progress?.report({ message: "Finalizing installation...", increment: 3 });
|
|
921
|
+
}
|
|
922
|
+
async function installSdkFromArchive(opts) {
|
|
923
|
+
const { config, archivePath, progress, abortSignal } = opts;
|
|
924
|
+
const logger = opts.logger ?? noopLogger;
|
|
925
|
+
if (!fs10.statSync(archivePath, { throwIfNoEntry: false })?.isFile()) {
|
|
926
|
+
throw new OniroError(`SDK archive not found: ${archivePath}`);
|
|
927
|
+
}
|
|
928
|
+
const osFolder = getOsFolder();
|
|
929
|
+
const what = `the SDK install from '${path10.basename(archivePath)}'`;
|
|
930
|
+
const sdkRoot = getSdkRootDir(config);
|
|
931
|
+
const { dir: tmpDir, root: tmpRoot } = createInstallTempDir({
|
|
932
|
+
config,
|
|
933
|
+
override: opts.tmpDir,
|
|
934
|
+
installRoot: sdkRoot,
|
|
935
|
+
prefix: "oniro-sdk-",
|
|
936
|
+
logger
|
|
937
|
+
});
|
|
938
|
+
const extractDir = path10.join(tmpDir, "extract");
|
|
939
|
+
fs10.mkdirSync(extractDir);
|
|
940
|
+
const checkCancelled = () => {
|
|
941
|
+
if (abortSignal?.aborted) throw new CancelledError();
|
|
942
|
+
};
|
|
943
|
+
try {
|
|
944
|
+
progress?.report({ message: "Extracting SDK archive (this may take a while)...", increment: 0 });
|
|
945
|
+
await extractTarball(archivePath, extractDir, 0, (p) => p.split("/").includes(osFolder));
|
|
946
|
+
progress?.report({ message: "Extracting SDK archive (this may take a while)...", increment: 40 });
|
|
947
|
+
checkCancelled();
|
|
948
|
+
const osContentPath = findSdkOsDir(extractDir, osFolder);
|
|
949
|
+
if (!osContentPath) {
|
|
950
|
+
throw new OniroError(
|
|
951
|
+
`No '${osFolder}' SDK components (a '${osFolder}' folder of ZIPs) found in ${archivePath}. Is it an OpenHarmony SDK archive for this OS?`
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
const { api, version } = await readSdkComponentsMeta(osContentPath);
|
|
955
|
+
const sdkInstallDir = path10.join(sdkRoot, osFolder, api);
|
|
956
|
+
if (fs10.existsSync(sdkInstallDir) && !opts.force) {
|
|
957
|
+
throw new OniroError(
|
|
958
|
+
`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.`
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
fs10.mkdirSync(path10.dirname(sdkInstallDir), { recursive: true });
|
|
962
|
+
await installComponents({ osContentPath, sdkInstallDir, progress, logger, start: 40, range: 55, checkCancelled });
|
|
963
|
+
progress?.report({ message: "Cleaning up...", increment: 0 });
|
|
964
|
+
removeTempWorkDir(tmpDir, tmpRoot);
|
|
965
|
+
progress?.report({ message: "Cleaning up...", increment: 2 });
|
|
966
|
+
return { api, version, dir: sdkInstallDir };
|
|
967
|
+
} catch (err) {
|
|
968
|
+
removeTempWorkDir(tmpDir, tmpRoot);
|
|
969
|
+
throw toSpaceError(err, tmpRoot, what);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
function findSdkOsDir(root, osFolder, maxDepth = 4) {
|
|
973
|
+
let level = [root];
|
|
974
|
+
for (let depth = 0; depth < maxDepth && level.length > 0; depth++) {
|
|
975
|
+
const next = [];
|
|
976
|
+
for (const dir of level) {
|
|
977
|
+
for (const entry of fs10.readdirSync(dir, { withFileTypes: true })) {
|
|
978
|
+
if (!entry.isDirectory()) continue;
|
|
979
|
+
const p = path10.join(dir, entry.name);
|
|
980
|
+
if (entry.name === osFolder && fs10.readdirSync(p).some((n) => n.endsWith(".zip"))) return p;
|
|
981
|
+
next.push(p);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
level = next;
|
|
985
|
+
}
|
|
986
|
+
return void 0;
|
|
987
|
+
}
|
|
988
|
+
async function readSdkComponentsMeta(dir) {
|
|
989
|
+
const zips = fs10.readdirSync(dir).filter((n) => n.endsWith(".zip")).sort((a, b) => Number(b.startsWith("ets-")) - Number(a.startsWith("ets-")));
|
|
990
|
+
for (const name of zips) {
|
|
991
|
+
const data = await readZipEntry(path10.join(dir, name), (e) => /^[^/]+\/oh-uni-package\.json$/.test(e));
|
|
992
|
+
if (!data) continue;
|
|
993
|
+
try {
|
|
994
|
+
const pkg = JSON.parse(data.toString("utf8"));
|
|
995
|
+
const api = String(pkg.apiVersion ?? "");
|
|
996
|
+
if (/^\d+$/.test(api)) return { api, version: String(pkg.version ?? "") };
|
|
997
|
+
} catch {
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
throw new OniroError("No SDK component in the archive declares a numeric apiVersion (oh-uni-package.json).");
|
|
1001
|
+
}
|
|
910
1002
|
|
|
911
1003
|
// src/cmdTools/install.ts
|
|
912
1004
|
import * as fs11 from "fs";
|
|
@@ -1605,6 +1697,7 @@ import { spawn as spawn2 } from "child_process";
|
|
|
1605
1697
|
|
|
1606
1698
|
// src/hdc/exec.ts
|
|
1607
1699
|
import * as fs15 from "fs";
|
|
1700
|
+
import { StringDecoder } from "string_decoder";
|
|
1608
1701
|
function errorMessage(err) {
|
|
1609
1702
|
return err instanceof Error ? err.message : String(err);
|
|
1610
1703
|
}
|
|
@@ -1632,6 +1725,8 @@ function runProcess(opts) {
|
|
|
1632
1725
|
let stderr = "";
|
|
1633
1726
|
let settled = false;
|
|
1634
1727
|
let timedOut = false;
|
|
1728
|
+
const stdoutDecoder = new StringDecoder("utf8");
|
|
1729
|
+
const stderrDecoder = new StringDecoder("utf8");
|
|
1635
1730
|
const cleanup = () => {
|
|
1636
1731
|
clearTimeout(timer);
|
|
1637
1732
|
abortSignal?.removeEventListener("abort", onAbort);
|
|
@@ -1649,14 +1744,14 @@ function runProcess(opts) {
|
|
|
1649
1744
|
}, timeoutMs);
|
|
1650
1745
|
abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
1651
1746
|
child.stdout?.on("data", (d) => {
|
|
1652
|
-
const s =
|
|
1747
|
+
const s = stdoutDecoder.write(d);
|
|
1653
1748
|
stdout += s;
|
|
1654
|
-
onOutput?.(s, "stdout");
|
|
1749
|
+
if (s) onOutput?.(s, "stdout");
|
|
1655
1750
|
});
|
|
1656
1751
|
child.stderr?.on("data", (d) => {
|
|
1657
|
-
const s =
|
|
1752
|
+
const s = stderrDecoder.write(d);
|
|
1658
1753
|
stderr += s;
|
|
1659
|
-
onOutput?.(s, "stderr");
|
|
1754
|
+
if (s) onOutput?.(s, "stderr");
|
|
1660
1755
|
});
|
|
1661
1756
|
child.on("error", (err) => {
|
|
1662
1757
|
if (settled) return;
|
|
@@ -1668,6 +1763,12 @@ function runProcess(opts) {
|
|
|
1668
1763
|
if (settled) return;
|
|
1669
1764
|
settled = true;
|
|
1670
1765
|
cleanup();
|
|
1766
|
+
const stdoutTail = stdoutDecoder.end();
|
|
1767
|
+
const stderrTail = stderrDecoder.end();
|
|
1768
|
+
stdout += stdoutTail;
|
|
1769
|
+
stderr += stderrTail;
|
|
1770
|
+
if (stdoutTail) onOutput?.(stdoutTail, "stdout");
|
|
1771
|
+
if (stderrTail) onOutput?.(stderrTail, "stderr");
|
|
1671
1772
|
if (timedOut) {
|
|
1672
1773
|
reject(
|
|
1673
1774
|
new OniroError(
|
|
@@ -1955,6 +2056,7 @@ async function getEmulatorStatus(config, opts = {}) {
|
|
|
1955
2056
|
// src/hdc/devices.ts
|
|
1956
2057
|
var STATUS_TOKENS = /* @__PURE__ */ new Set([
|
|
1957
2058
|
"Connected",
|
|
2059
|
+
"Ready",
|
|
1958
2060
|
"Offline",
|
|
1959
2061
|
"Unauthorized",
|
|
1960
2062
|
"Authorizing",
|
|
@@ -2184,9 +2286,13 @@ function moduleOfHap(hapFileName) {
|
|
|
2184
2286
|
const dash = hapFileName.indexOf("-");
|
|
2185
2287
|
return dash > 0 ? hapFileName.slice(0, dash) : hapFileName.replace(/\.hap$/i, "");
|
|
2186
2288
|
}
|
|
2289
|
+
function isAppProjectRoot(dir) {
|
|
2290
|
+
return fs17.existsSync(path18.join(dir, "AppScope", "app.json5"));
|
|
2291
|
+
}
|
|
2187
2292
|
async function discoverHaps(opts) {
|
|
2188
2293
|
const { projectDir } = opts;
|
|
2189
2294
|
const maxDepth = opts.maxDepth ?? 8;
|
|
2295
|
+
const skipNestedProjects = isAppProjectRoot(projectDir);
|
|
2190
2296
|
const result = {};
|
|
2191
2297
|
const walk = async (dir, depth) => {
|
|
2192
2298
|
if (depth > maxDepth) return;
|
|
@@ -2195,6 +2301,7 @@ async function discoverHaps(opts) {
|
|
|
2195
2301
|
const full = path18.join(dir, e.name);
|
|
2196
2302
|
if (e.isDirectory()) {
|
|
2197
2303
|
if (e.name === "node_modules" || e.name === "oh_modules" || e.name === ".git") continue;
|
|
2304
|
+
if (skipNestedProjects && isAppProjectRoot(full)) continue;
|
|
2198
2305
|
await walk(full, depth + 1);
|
|
2199
2306
|
} else if (e.isFile() && e.name.endsWith(".hap")) {
|
|
2200
2307
|
const moduleName = moduleOfHap(e.name);
|
|
@@ -3386,6 +3493,54 @@ async function resolveProcessId(config, bundle, deviceSerial) {
|
|
|
3386
3493
|
const proc = await findRunningProcess({ config, bundle, deviceSerial });
|
|
3387
3494
|
return proc?.pid;
|
|
3388
3495
|
}
|
|
3496
|
+
async function readDeviceClock(config, deviceSerial) {
|
|
3497
|
+
try {
|
|
3498
|
+
const res = await shell({ config, command: "date +%Y-%m-%dT%H:%M:%S", deviceSerial, timeoutMs: 1e4 });
|
|
3499
|
+
const m = res.code === 0 ? /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/.exec(res.stdout) : null;
|
|
3500
|
+
if (!m) return null;
|
|
3501
|
+
const [year, month, day, hour, minute, second] = m.slice(1).map(Number);
|
|
3502
|
+
return Date.UTC(year, month - 1, day, hour, minute, second);
|
|
3503
|
+
} catch {
|
|
3504
|
+
return null;
|
|
3505
|
+
}
|
|
3506
|
+
}
|
|
3507
|
+
function hilogTimeMs(time, referenceMs) {
|
|
3508
|
+
const m = /^(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})\.(\d{3})$/.exec(time);
|
|
3509
|
+
if (!m) return null;
|
|
3510
|
+
const [month, day, hour, minute, second, ms] = m.slice(1).map(Number);
|
|
3511
|
+
const year = new Date(referenceMs).getUTCFullYear();
|
|
3512
|
+
let best = null;
|
|
3513
|
+
for (const y of [year - 1, year, year + 1]) {
|
|
3514
|
+
const t = Date.UTC(y, month - 1, day, hour, minute, second, ms);
|
|
3515
|
+
if (best === null || Math.abs(t - referenceMs) < Math.abs(best - referenceMs)) best = t;
|
|
3516
|
+
}
|
|
3517
|
+
return best;
|
|
3518
|
+
}
|
|
3519
|
+
async function recentEntryFilter(opts) {
|
|
3520
|
+
const passAll = { test: () => true, afterReconnect: async () => {
|
|
3521
|
+
} };
|
|
3522
|
+
const lookbackMs = opts.lookbackMs ?? 0;
|
|
3523
|
+
if (lookbackMs === Infinity) return passAll;
|
|
3524
|
+
const startedAt = Date.now();
|
|
3525
|
+
const now = await readDeviceClock(opts.config, opts.deviceSerial);
|
|
3526
|
+
if (now === null) {
|
|
3527
|
+
opts.logger.warn("Could not read the device clock, so lines already in the log buffer can match too.");
|
|
3528
|
+
return passAll;
|
|
3529
|
+
}
|
|
3530
|
+
let since = now - (Date.now() - startedAt) - lookbackMs;
|
|
3531
|
+
return {
|
|
3532
|
+
test: (entry) => {
|
|
3533
|
+
if (since === null) return true;
|
|
3534
|
+
const t = hilogTimeMs(entry.time, now);
|
|
3535
|
+
return t === null || t >= since;
|
|
3536
|
+
},
|
|
3537
|
+
afterReconnect: async () => {
|
|
3538
|
+
if (since === null) return;
|
|
3539
|
+
const later = await readDeviceClock(opts.config, opts.deviceSerial);
|
|
3540
|
+
if (later !== null && later < since) since = null;
|
|
3541
|
+
}
|
|
3542
|
+
};
|
|
3543
|
+
}
|
|
3389
3544
|
function waitForLog(opts) {
|
|
3390
3545
|
return new Promise((resolve7, reject) => {
|
|
3391
3546
|
const deadline = Date.now() + opts.timeoutMs;
|
|
@@ -3393,6 +3548,8 @@ function waitForLog(opts) {
|
|
|
3393
3548
|
let child = null;
|
|
3394
3549
|
let reconnectTimer;
|
|
3395
3550
|
let buf = "";
|
|
3551
|
+
let recent = { test: () => true, afterReconnect: async () => {
|
|
3552
|
+
} };
|
|
3396
3553
|
const cleanup = () => {
|
|
3397
3554
|
clearTimeout(timer);
|
|
3398
3555
|
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
@@ -3433,7 +3590,7 @@ function waitForLog(opts) {
|
|
|
3433
3590
|
buf = lines.pop() ?? "";
|
|
3434
3591
|
for (const line of lines) {
|
|
3435
3592
|
const entry = parseHilogLine(line);
|
|
3436
|
-
if (entry && opts.pattern.test(entryText(entry))) {
|
|
3593
|
+
if (entry && recent.test(entry) && opts.pattern.test(entryText(entry))) {
|
|
3437
3594
|
finish(entry);
|
|
3438
3595
|
return;
|
|
3439
3596
|
}
|
|
@@ -3443,13 +3600,21 @@ function waitForLog(opts) {
|
|
|
3443
3600
|
if (settled || child !== stream) return;
|
|
3444
3601
|
child = null;
|
|
3445
3602
|
if (Date.now() < deadline) {
|
|
3446
|
-
reconnectTimer = setTimeout(() => void
|
|
3603
|
+
reconnectTimer = setTimeout(() => void recent.afterReconnect().then(spawnStream).catch(failWith), 1e3);
|
|
3447
3604
|
}
|
|
3448
3605
|
};
|
|
3449
3606
|
stream.once("close", onEnd);
|
|
3450
3607
|
stream.once("error", onEnd);
|
|
3451
3608
|
};
|
|
3452
|
-
void
|
|
3609
|
+
void (async () => {
|
|
3610
|
+
recent = await recentEntryFilter({
|
|
3611
|
+
config: opts.config,
|
|
3612
|
+
deviceSerial: opts.deviceSerial,
|
|
3613
|
+
lookbackMs: opts.lookbackMs,
|
|
3614
|
+
logger: opts.logger ?? noopLogger
|
|
3615
|
+
});
|
|
3616
|
+
await spawnStream();
|
|
3617
|
+
})().catch(failWith);
|
|
3453
3618
|
});
|
|
3454
3619
|
}
|
|
3455
3620
|
function watchLog(opts) {
|
|
@@ -3458,6 +3623,8 @@ function watchLog(opts) {
|
|
|
3458
3623
|
let settled = false;
|
|
3459
3624
|
let child = null;
|
|
3460
3625
|
let buf = "";
|
|
3626
|
+
let recent = { test: () => true, afterReconnect: async () => {
|
|
3627
|
+
} };
|
|
3461
3628
|
const cleanup = () => {
|
|
3462
3629
|
clearTimeout(timer);
|
|
3463
3630
|
opts.abortSignal?.removeEventListener("abort", onAbort);
|
|
@@ -3481,6 +3648,13 @@ function watchLog(opts) {
|
|
|
3481
3648
|
const timer = setTimeout(done, opts.durationMs);
|
|
3482
3649
|
opts.abortSignal?.addEventListener("abort", onAbort, { once: true });
|
|
3483
3650
|
void (async () => {
|
|
3651
|
+
recent = await recentEntryFilter({
|
|
3652
|
+
config: opts.config,
|
|
3653
|
+
deviceSerial: opts.deviceSerial,
|
|
3654
|
+
lookbackMs: opts.lookbackMs,
|
|
3655
|
+
logger: opts.logger ?? noopLogger
|
|
3656
|
+
});
|
|
3657
|
+
if (settled) return;
|
|
3484
3658
|
const processId = await resolveProcessId(opts.config, opts.bundle, opts.deviceSerial);
|
|
3485
3659
|
if (settled) return;
|
|
3486
3660
|
const stream = streamHilog({ config: opts.config, processId, domain: opts.domain, deviceSerial: opts.deviceSerial });
|
|
@@ -3491,7 +3665,7 @@ function watchLog(opts) {
|
|
|
3491
3665
|
buf = lines.pop() ?? "";
|
|
3492
3666
|
for (const line of lines) {
|
|
3493
3667
|
const entry = parseHilogLine(line);
|
|
3494
|
-
if (entry && opts.pattern.test(entryText(entry))) matches.push(entry);
|
|
3668
|
+
if (entry && recent.test(entry) && opts.pattern.test(entryText(entry))) matches.push(entry);
|
|
3495
3669
|
}
|
|
3496
3670
|
});
|
|
3497
3671
|
})().catch((err) => {
|
|
@@ -3776,6 +3950,8 @@ async function ensureOhModules(opts) {
|
|
|
3776
3950
|
}
|
|
3777
3951
|
|
|
3778
3952
|
// src/build/codelinter.ts
|
|
3953
|
+
import * as fs26 from "fs";
|
|
3954
|
+
import * as path26 from "path";
|
|
3779
3955
|
var FINDING_RE = /^(.*?):(\d+):(?:(\d+):)?\s*(error|warning|warn|suggestion|info)\b[:\s-]*(.*)$/i;
|
|
3780
3956
|
var TRAILING_CODE_RE = /[([]([\w@/.\-]+)[)\]]\s*$/;
|
|
3781
3957
|
var FILE_HEADER_RE = /^(.+\.\w+)\((\d+)\)$/;
|
|
@@ -3862,6 +4038,16 @@ function parseCodelinterReport(output) {
|
|
|
3862
4038
|
function parseCodelinterFindings(output) {
|
|
3863
4039
|
return parseCodelinterReport(output).findings;
|
|
3864
4040
|
}
|
|
4041
|
+
var PROJECT_ROOT_FILES = [
|
|
4042
|
+
["build-profile.json5"],
|
|
4043
|
+
["hvigorfile.ts", "hvigorfile.js"],
|
|
4044
|
+
[path26.join("hvigor", "hvigor-config.json5")]
|
|
4045
|
+
];
|
|
4046
|
+
function missingProjectRootFiles(projectDir) {
|
|
4047
|
+
return PROJECT_ROOT_FILES.filter((names) => !names.some((f) => fs26.existsSync(path26.join(projectDir, f)))).map(
|
|
4048
|
+
(names) => names[0]
|
|
4049
|
+
);
|
|
4050
|
+
}
|
|
3865
4051
|
async function runCodelinter(opts) {
|
|
3866
4052
|
const res = await runProcess({
|
|
3867
4053
|
command: getCmdToolsBin(opts.config, "codelinter"),
|
|
@@ -3879,7 +4065,7 @@ async function runCodelinter(opts) {
|
|
|
3879
4065
|
var DIAGNOSIS_OUTPUT_LIMIT = 2e6;
|
|
3880
4066
|
function diagnoseBuildFailure(output) {
|
|
3881
4067
|
if (/is not exported from Kit|has no exported member .*@systemapi/i.test(output)) {
|
|
3882
|
-
return
|
|
4068
|
+
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\`).`;
|
|
3883
4069
|
}
|
|
3884
4070
|
if (/00308018|SDK path does not exist|SDK license agreement is not accepted/i.test(output)) {
|
|
3885
4071
|
return "hvigor cannot find the SDK the project compiles against: check `oniro-app sdk list` against compileSdkVersion.";
|
|
@@ -3951,21 +4137,21 @@ function isValidBundleName(bundleName) {
|
|
|
3951
4137
|
}
|
|
3952
4138
|
|
|
3953
4139
|
// src/project/templates.ts
|
|
3954
|
-
import * as
|
|
3955
|
-
import * as
|
|
4140
|
+
import * as fs27 from "fs";
|
|
4141
|
+
import * as path27 from "path";
|
|
3956
4142
|
function toHumanTemplateName(folderName) {
|
|
3957
4143
|
return folderName.replace(/([a-z])([A-Z])/g, "$1 $2");
|
|
3958
4144
|
}
|
|
3959
4145
|
function listTemplates(templateRoot) {
|
|
3960
|
-
if (!
|
|
3961
|
-
const entries =
|
|
4146
|
+
if (!fs27.existsSync(templateRoot)) return [];
|
|
4147
|
+
const entries = fs27.readdirSync(templateRoot, { withFileTypes: true });
|
|
3962
4148
|
return entries.filter((e) => e.isDirectory()).map((e) => {
|
|
3963
|
-
const dir =
|
|
3964
|
-
const metaPath =
|
|
4149
|
+
const dir = path27.join(templateRoot, e.name);
|
|
4150
|
+
const metaPath = path27.join(dir, "template.json");
|
|
3965
4151
|
let meta = {};
|
|
3966
|
-
if (
|
|
4152
|
+
if (fs27.existsSync(metaPath)) {
|
|
3967
4153
|
try {
|
|
3968
|
-
meta = JSON.parse(
|
|
4154
|
+
meta = JSON.parse(fs27.readFileSync(metaPath, "utf8"));
|
|
3969
4155
|
} catch {
|
|
3970
4156
|
}
|
|
3971
4157
|
}
|
|
@@ -3980,57 +4166,57 @@ function listTemplates(templateRoot) {
|
|
|
3980
4166
|
function validateTemplateLayout(templateDir, defaultModuleName) {
|
|
3981
4167
|
const required = [
|
|
3982
4168
|
"build-profile.json5",
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4169
|
+
path27.join("AppScope", "app.json5"),
|
|
4170
|
+
path27.join(defaultModuleName, "src", "main", "module.json5"),
|
|
4171
|
+
path27.join(defaultModuleName, "oh-package.json5"),
|
|
3986
4172
|
"hvigorfile.ts"
|
|
3987
4173
|
];
|
|
3988
|
-
return required.filter((rel) => !
|
|
4174
|
+
return required.filter((rel) => !fs27.existsSync(path27.join(templateDir, rel)));
|
|
3989
4175
|
}
|
|
3990
4176
|
|
|
3991
4177
|
// src/project/createScaffold.ts
|
|
3992
|
-
import * as
|
|
3993
|
-
import * as
|
|
4178
|
+
import * as fs29 from "fs";
|
|
4179
|
+
import * as path28 from "path";
|
|
3994
4180
|
|
|
3995
4181
|
// src/project/jsonHelpers.ts
|
|
3996
|
-
import * as
|
|
4182
|
+
import * as fs28 from "fs";
|
|
3997
4183
|
import JSON55 from "json5";
|
|
3998
4184
|
function readJson5File(filePath) {
|
|
3999
|
-
return JSON55.parse(
|
|
4185
|
+
return JSON55.parse(fs28.readFileSync(filePath, "utf8"));
|
|
4000
4186
|
}
|
|
4001
4187
|
function writeJson5File(filePath, value) {
|
|
4002
|
-
|
|
4188
|
+
fs28.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
4003
4189
|
}
|
|
4004
4190
|
function readJsonFile(filePath) {
|
|
4005
|
-
return JSON.parse(
|
|
4191
|
+
return JSON.parse(fs28.readFileSync(filePath, "utf8"));
|
|
4006
4192
|
}
|
|
4007
4193
|
function writeJsonFile(filePath, value) {
|
|
4008
|
-
|
|
4194
|
+
fs28.writeFileSync(filePath, JSON.stringify(value, null, 2) + "\n", "utf8");
|
|
4009
4195
|
}
|
|
4010
4196
|
|
|
4011
4197
|
// src/project/createScaffold.ts
|
|
4012
4198
|
var IGNORED_DIRS = /* @__PURE__ */ new Set(["oh_modules", "node_modules", "build", ".hvigor"]);
|
|
4013
4199
|
async function pathExists(p) {
|
|
4014
4200
|
try {
|
|
4015
|
-
await
|
|
4201
|
+
await fs29.promises.access(p);
|
|
4016
4202
|
return true;
|
|
4017
4203
|
} catch {
|
|
4018
4204
|
return false;
|
|
4019
4205
|
}
|
|
4020
4206
|
}
|
|
4021
4207
|
async function copyDirRecursive(srcDir, destDir) {
|
|
4022
|
-
await
|
|
4023
|
-
const entries = await
|
|
4208
|
+
await fs29.promises.mkdir(destDir, { recursive: true });
|
|
4209
|
+
const entries = await fs29.promises.readdir(srcDir, { withFileTypes: true });
|
|
4024
4210
|
for (const entry of entries) {
|
|
4025
|
-
const src =
|
|
4026
|
-
const dest =
|
|
4211
|
+
const src = path28.join(srcDir, entry.name);
|
|
4212
|
+
const dest = path28.join(destDir, entry.name);
|
|
4027
4213
|
if (entry.isDirectory()) {
|
|
4028
4214
|
await copyDirRecursive(src, dest);
|
|
4029
4215
|
} else if (entry.isSymbolicLink()) {
|
|
4030
4216
|
continue;
|
|
4031
4217
|
} else if (entry.isFile()) {
|
|
4032
4218
|
if (entry.name === "template.json") continue;
|
|
4033
|
-
await
|
|
4219
|
+
await fs29.promises.copyFile(src, dest);
|
|
4034
4220
|
}
|
|
4035
4221
|
}
|
|
4036
4222
|
}
|
|
@@ -4038,9 +4224,9 @@ async function normalizeJson5ToJson(projectDir, logger) {
|
|
|
4038
4224
|
const stack = [projectDir];
|
|
4039
4225
|
while (stack.length > 0) {
|
|
4040
4226
|
const currentDir = stack.pop();
|
|
4041
|
-
const entries = await
|
|
4227
|
+
const entries = await fs29.promises.readdir(currentDir, { withFileTypes: true });
|
|
4042
4228
|
for (const entry of entries) {
|
|
4043
|
-
const fullPath =
|
|
4229
|
+
const fullPath = path28.join(currentDir, entry.name);
|
|
4044
4230
|
if (entry.isDirectory()) {
|
|
4045
4231
|
if (IGNORED_DIRS.has(entry.name)) continue;
|
|
4046
4232
|
stack.push(fullPath);
|
|
@@ -4062,23 +4248,23 @@ function toJavaPropertiesPath(p) {
|
|
|
4062
4248
|
function createOrUpdateLocalProperties(projectDir, sdkDir) {
|
|
4063
4249
|
const content = `sdk.dir=${toJavaPropertiesPath(sdkDir)}
|
|
4064
4250
|
`;
|
|
4065
|
-
|
|
4251
|
+
fs29.writeFileSync(path28.join(projectDir, "local.properties"), content, "utf8");
|
|
4066
4252
|
}
|
|
4067
4253
|
function renameIfExists(fromPath, toPath) {
|
|
4068
|
-
if (
|
|
4069
|
-
|
|
4254
|
+
if (fs29.existsSync(fromPath) && fromPath !== toPath) {
|
|
4255
|
+
fs29.renameSync(fromPath, toPath);
|
|
4070
4256
|
}
|
|
4071
4257
|
}
|
|
4072
4258
|
function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
4073
|
-
const appJsonPath =
|
|
4074
|
-
if (
|
|
4259
|
+
const appJsonPath = path28.join(projectDir, "AppScope", "app.json5");
|
|
4260
|
+
if (fs29.existsSync(appJsonPath)) {
|
|
4075
4261
|
const appJson = readJson5File(appJsonPath);
|
|
4076
4262
|
appJson.app = appJson.app ?? {};
|
|
4077
4263
|
appJson.app.bundleName = args.bundleName;
|
|
4078
4264
|
writeJson5File(appJsonPath, appJson);
|
|
4079
4265
|
}
|
|
4080
|
-
const stringsPath =
|
|
4081
|
-
if (
|
|
4266
|
+
const stringsPath = path28.join(projectDir, "AppScope", "resources", "base", "element", "string.json");
|
|
4267
|
+
if (fs29.existsSync(stringsPath)) {
|
|
4082
4268
|
const strings = readJsonFile(stringsPath);
|
|
4083
4269
|
if (Array.isArray(strings.string)) {
|
|
4084
4270
|
const appName = strings.string.find((s) => s.name === "app_name");
|
|
@@ -4086,8 +4272,8 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
|
4086
4272
|
}
|
|
4087
4273
|
writeJsonFile(stringsPath, strings);
|
|
4088
4274
|
}
|
|
4089
|
-
const buildProfilePath =
|
|
4090
|
-
if (
|
|
4275
|
+
const buildProfilePath = path28.join(projectDir, "build-profile.json5");
|
|
4276
|
+
if (fs29.existsSync(buildProfilePath)) {
|
|
4091
4277
|
const buildProfile = readJson5File(buildProfilePath);
|
|
4092
4278
|
buildProfile.app = buildProfile.app ?? {};
|
|
4093
4279
|
if (Array.isArray(buildProfile.app.products) && buildProfile.app.products.length > 0) {
|
|
@@ -4100,23 +4286,23 @@ function updateTemplateConfigs(projectDir, args, sdkBaseDir) {
|
|
|
4100
4286
|
}
|
|
4101
4287
|
writeJson5File(buildProfilePath, buildProfile);
|
|
4102
4288
|
}
|
|
4103
|
-
const moduleJsonPath =
|
|
4104
|
-
if (
|
|
4289
|
+
const moduleJsonPath = path28.join(projectDir, args.moduleName, "src", "main", "module.json5");
|
|
4290
|
+
if (fs29.existsSync(moduleJsonPath)) {
|
|
4105
4291
|
const moduleJson = readJson5File(moduleJsonPath);
|
|
4106
4292
|
moduleJson.module = moduleJson.module ?? {};
|
|
4107
4293
|
moduleJson.module.name = args.moduleName;
|
|
4108
4294
|
writeJson5File(moduleJsonPath, moduleJson);
|
|
4109
4295
|
}
|
|
4110
|
-
const moduleOhPackagePath =
|
|
4111
|
-
if (
|
|
4296
|
+
const moduleOhPackagePath = path28.join(projectDir, args.moduleName, "oh-package.json5");
|
|
4297
|
+
if (fs29.existsSync(moduleOhPackagePath)) {
|
|
4112
4298
|
const pkg = readJson5File(moduleOhPackagePath);
|
|
4113
4299
|
pkg.name = args.moduleName;
|
|
4114
4300
|
writeJson5File(moduleOhPackagePath, pkg);
|
|
4115
4301
|
}
|
|
4116
|
-
const vscodeDir =
|
|
4117
|
-
|
|
4302
|
+
const vscodeDir = path28.join(projectDir, ".vscode");
|
|
4303
|
+
fs29.mkdirSync(vscodeDir, { recursive: true });
|
|
4118
4304
|
const hapPath = `${args.moduleName}/build/default/outputs/default/${args.moduleName}-default-signed.hap`;
|
|
4119
|
-
writeJsonFile(
|
|
4305
|
+
writeJsonFile(path28.join(vscodeDir, "settings.json"), {
|
|
4120
4306
|
"oniro.hapPath": hapPath,
|
|
4121
4307
|
"files.associations": { "*.json5": "jsonc" }
|
|
4122
4308
|
});
|
|
@@ -4133,7 +4319,7 @@ async function createScaffold(opts) {
|
|
|
4133
4319
|
if (!opts.location || !await pathExists(opts.location)) {
|
|
4134
4320
|
throw new OniroError(`Location does not exist: ${opts.location}`);
|
|
4135
4321
|
}
|
|
4136
|
-
const templateDir =
|
|
4322
|
+
const templateDir = path28.join(opts.templateRoot, opts.templateId);
|
|
4137
4323
|
if (!await pathExists(templateDir)) {
|
|
4138
4324
|
throw new OniroError(`Template not found: ${templateDir}`);
|
|
4139
4325
|
}
|
|
@@ -4168,17 +4354,17 @@ async function createScaffold(opts) {
|
|
|
4168
4354
|
}
|
|
4169
4355
|
}
|
|
4170
4356
|
}
|
|
4171
|
-
const projectDir =
|
|
4357
|
+
const projectDir = path28.join(opts.location, opts.projectName);
|
|
4172
4358
|
if (await pathExists(projectDir)) {
|
|
4173
4359
|
if (!opts.overwrite) {
|
|
4174
4360
|
throw new OniroError(`Destination already exists: ${projectDir}. Pass overwrite: true to replace it.`);
|
|
4175
4361
|
}
|
|
4176
|
-
await
|
|
4362
|
+
await fs29.promises.rm(projectDir, { recursive: true, force: true });
|
|
4177
4363
|
}
|
|
4178
4364
|
logger.info(`[create] Scaffolding ${opts.templateId} at ${projectDir}`);
|
|
4179
4365
|
await copyDirRecursive(templateDir, projectDir);
|
|
4180
4366
|
if (moduleName !== defaultModuleName) {
|
|
4181
|
-
renameIfExists(
|
|
4367
|
+
renameIfExists(path28.join(projectDir, defaultModuleName), path28.join(projectDir, moduleName));
|
|
4182
4368
|
}
|
|
4183
4369
|
updateTemplateConfigs(
|
|
4184
4370
|
projectDir,
|
|
@@ -4195,11 +4381,11 @@ async function createScaffold(opts) {
|
|
|
4195
4381
|
}
|
|
4196
4382
|
|
|
4197
4383
|
// src/project/listModules.ts
|
|
4198
|
-
import * as
|
|
4199
|
-
import * as
|
|
4384
|
+
import * as fs30 from "fs";
|
|
4385
|
+
import * as path29 from "path";
|
|
4200
4386
|
function listModules(opts) {
|
|
4201
|
-
const buildProfile =
|
|
4202
|
-
if (!
|
|
4387
|
+
const buildProfile = path29.join(opts.projectDir, "build-profile.json5");
|
|
4388
|
+
if (!fs30.existsSync(buildProfile)) {
|
|
4203
4389
|
throw new OniroError(`build-profile.json5 not found at ${buildProfile}`);
|
|
4204
4390
|
}
|
|
4205
4391
|
const parsed = readJson5File(buildProfile);
|
|
@@ -4211,12 +4397,12 @@ function listModules(opts) {
|
|
|
4211
4397
|
}
|
|
4212
4398
|
|
|
4213
4399
|
// src/project/abilities.ts
|
|
4214
|
-
import * as
|
|
4215
|
-
import * as
|
|
4400
|
+
import * as fs31 from "fs";
|
|
4401
|
+
import * as path30 from "path";
|
|
4216
4402
|
function listAbilities(opts) {
|
|
4217
4403
|
const moduleName = opts.moduleName ?? "entry";
|
|
4218
|
-
const moduleJsonPath =
|
|
4219
|
-
if (!
|
|
4404
|
+
const moduleJsonPath = path30.join(opts.projectDir, moduleName, "src", "main", "module.json5");
|
|
4405
|
+
if (!fs31.existsSync(moduleJsonPath)) {
|
|
4220
4406
|
throw new OniroError(`Could not find module.json5 at ${moduleJsonPath}`);
|
|
4221
4407
|
}
|
|
4222
4408
|
const parsed = readJson5File(moduleJsonPath);
|
|
@@ -4224,12 +4410,12 @@ function listAbilities(opts) {
|
|
|
4224
4410
|
}
|
|
4225
4411
|
|
|
4226
4412
|
// src/project/prepareSigning.ts
|
|
4227
|
-
import * as
|
|
4228
|
-
import * as
|
|
4413
|
+
import * as fs32 from "fs";
|
|
4414
|
+
import * as path31 from "path";
|
|
4229
4415
|
function hasSigningArtifacts(dir) {
|
|
4230
|
-
if (!
|
|
4231
|
-
const buildProfile =
|
|
4232
|
-
if (!
|
|
4416
|
+
if (!fs32.existsSync(path31.join(dir, "signatures"))) return false;
|
|
4417
|
+
const buildProfile = path31.join(dir, "build-profile.json5");
|
|
4418
|
+
if (!fs32.existsSync(buildProfile)) return false;
|
|
4233
4419
|
try {
|
|
4234
4420
|
const parsed = readJson5File(buildProfile);
|
|
4235
4421
|
return Array.isArray(parsed.app?.signingConfigs) && parsed.app.signingConfigs.length > 0;
|
|
@@ -4332,8 +4518,25 @@ async function diffHapAssets(opts) {
|
|
|
4332
4518
|
}
|
|
4333
4519
|
|
|
4334
4520
|
// src/install/apply.ts
|
|
4335
|
-
import * as
|
|
4336
|
-
import * as
|
|
4521
|
+
import * as fs33 from "fs";
|
|
4522
|
+
import * as path32 from "path";
|
|
4523
|
+
|
|
4524
|
+
// src/install/hapBundleName.ts
|
|
4525
|
+
function bundleNameFromHapConfig(text) {
|
|
4526
|
+
try {
|
|
4527
|
+
const parsed = JSON.parse(text.replace(/^/, ""));
|
|
4528
|
+
const name = parsed.app?.bundleName;
|
|
4529
|
+
return typeof name === "string" && name ? name : null;
|
|
4530
|
+
} catch {
|
|
4531
|
+
return null;
|
|
4532
|
+
}
|
|
4533
|
+
}
|
|
4534
|
+
async function readHapBundleName(hapPath) {
|
|
4535
|
+
const config = await readZipEntry(hapPath, (n) => n === "module.json") ?? await readZipEntry(hapPath, (n) => n === "config.json");
|
|
4536
|
+
return config ? bundleNameFromHapConfig(config.toString("utf8")) : null;
|
|
4537
|
+
}
|
|
4538
|
+
|
|
4539
|
+
// src/install/apply.ts
|
|
4337
4540
|
function decideInstallMethod(s) {
|
|
4338
4541
|
if (!s.signInfoInconsistent) return "replace";
|
|
4339
4542
|
if (s.isSystemBundle && !s.allowUninstall) return "refuse";
|
|
@@ -4354,7 +4557,7 @@ async function pidOf(config, bundle, deviceSerial) {
|
|
|
4354
4557
|
async function resolveHap(opts, logger) {
|
|
4355
4558
|
let hap;
|
|
4356
4559
|
if (opts.hapPath) {
|
|
4357
|
-
const hapPath = !
|
|
4560
|
+
const hapPath = !path32.isAbsolute(opts.hapPath) && opts.projectDir ? path32.join(opts.projectDir, opts.hapPath) : opts.hapPath;
|
|
4358
4561
|
hap = existingHapOrUnsigned(hapPath);
|
|
4359
4562
|
if (!hap) throw new OniroError(`HAP not found at ${hapPath}.`);
|
|
4360
4563
|
} else {
|
|
@@ -4363,7 +4566,7 @@ async function resolveHap(opts, logger) {
|
|
|
4363
4566
|
if (!picked) throw new OniroError(`No HAP found${opts.module ? ` for module ${opts.module}` : ""}. Build first.`);
|
|
4364
4567
|
hap = { path: picked.path, fallback: !picked.signed };
|
|
4365
4568
|
}
|
|
4366
|
-
if (hap.fallback) logger.warn(`No signed HAP found; installing the unsigned ${
|
|
4569
|
+
if (hap.fallback) logger.warn(`No signed HAP found; installing the unsigned ${path32.basename(hap.path)}.`);
|
|
4367
4570
|
return hap;
|
|
4368
4571
|
}
|
|
4369
4572
|
async function applyChanges(opts) {
|
|
@@ -4373,9 +4576,18 @@ async function applyChanges(opts) {
|
|
|
4373
4576
|
const allowUninstall = opts.allowUninstall ?? false;
|
|
4374
4577
|
const hap = await resolveHap(opts, logger);
|
|
4375
4578
|
const hapPath = hap.path;
|
|
4579
|
+
const hapBundle = await readHapBundleName(hapPath).catch((err) => {
|
|
4580
|
+
logger.debug(`bundle name check skipped: ${err.message}`);
|
|
4581
|
+
return null;
|
|
4582
|
+
});
|
|
4583
|
+
if (hapBundle && hapBundle !== bundle) {
|
|
4584
|
+
throw new OniroError(
|
|
4585
|
+
`${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.`
|
|
4586
|
+
);
|
|
4587
|
+
}
|
|
4376
4588
|
logger.info(`installing ${hapPath}`);
|
|
4377
4589
|
let assetsChanged = false;
|
|
4378
|
-
if (opts.installedHapPath &&
|
|
4590
|
+
if (opts.installedHapPath && fs33.existsSync(opts.installedHapPath)) {
|
|
4379
4591
|
try {
|
|
4380
4592
|
const diff = await diffHapAssets({ installedHap: opts.installedHapPath, newHap: hapPath });
|
|
4381
4593
|
assetsChanged = diff.addedAssetPaths.length > 0 || diff.removedAssetPaths.length > 0;
|
|
@@ -4408,7 +4620,7 @@ async function applyChanges(opts) {
|
|
|
4408
4620
|
}
|
|
4409
4621
|
if (!await isBundleInstalled({ config, bundle, deviceSerial })) {
|
|
4410
4622
|
throw new OniroError(
|
|
4411
|
-
`hdc reported ${
|
|
4623
|
+
`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).`
|
|
4412
4624
|
);
|
|
4413
4625
|
}
|
|
4414
4626
|
let postInstallPid = await pidOf(config, bundle, deviceSerial);
|
|
@@ -4485,9 +4697,9 @@ var AUTH_PATHS = {
|
|
|
4485
4697
|
};
|
|
4486
4698
|
|
|
4487
4699
|
// src/harmonyos/auth/tokenStore.ts
|
|
4488
|
-
import * as
|
|
4700
|
+
import * as fs34 from "fs";
|
|
4489
4701
|
import * as os11 from "os";
|
|
4490
|
-
import * as
|
|
4702
|
+
import * as path33 from "path";
|
|
4491
4703
|
import * as crypto3 from "crypto";
|
|
4492
4704
|
var ALGORITHM = "aes-256-gcm";
|
|
4493
4705
|
var KEY_LENGTH = 32;
|
|
@@ -4523,7 +4735,7 @@ function permissionHint(dir) {
|
|
|
4523
4735
|
}
|
|
4524
4736
|
function ensureDir(dir) {
|
|
4525
4737
|
try {
|
|
4526
|
-
|
|
4738
|
+
fs34.mkdirSync(dir, { recursive: true, mode: DIR_MODE });
|
|
4527
4739
|
} catch (err) {
|
|
4528
4740
|
if (err.code === "EACCES") {
|
|
4529
4741
|
throw new OniroError(permissionHint(dir), err);
|
|
@@ -4534,17 +4746,17 @@ function ensureDir(dir) {
|
|
|
4534
4746
|
function createTokenStore(opts) {
|
|
4535
4747
|
const logger = opts.logger ?? noopLogger;
|
|
4536
4748
|
const authDir = opts.config.get("harmonyosAuthDir", defaultPaths.harmonyosAuthDir());
|
|
4537
|
-
const tokenPath =
|
|
4538
|
-
const keyPath =
|
|
4749
|
+
const tokenPath = path33.join(authDir, TOKEN_FILE);
|
|
4750
|
+
const keyPath = path33.join(os11.homedir(), ".local", "share", "oniro-app", "keys", KEY_FILE);
|
|
4539
4751
|
function loadOrCreateKey() {
|
|
4540
|
-
if (
|
|
4541
|
-
const existing =
|
|
4752
|
+
if (fs34.existsSync(keyPath)) {
|
|
4753
|
+
const existing = fs34.readFileSync(keyPath);
|
|
4542
4754
|
if (existing.length === KEY_LENGTH) return existing;
|
|
4543
4755
|
logger.warn("[harmonyos] The token key file was malformed; regenerating (you will need to log in again).");
|
|
4544
4756
|
}
|
|
4545
|
-
ensureDir(
|
|
4757
|
+
ensureDir(path33.dirname(keyPath));
|
|
4546
4758
|
const key = crypto3.randomBytes(KEY_LENGTH);
|
|
4547
|
-
|
|
4759
|
+
fs34.writeFileSync(keyPath, key, { mode: FILE_MODE });
|
|
4548
4760
|
return key;
|
|
4549
4761
|
}
|
|
4550
4762
|
return {
|
|
@@ -4554,12 +4766,12 @@ function createTokenStore(opts) {
|
|
|
4554
4766
|
const payload = Buffer.from(JSON.stringify(session), "utf8");
|
|
4555
4767
|
const blob = encrypt2(loadOrCreateKey(), payload);
|
|
4556
4768
|
ensureDir(authDir);
|
|
4557
|
-
|
|
4769
|
+
fs34.writeFileSync(tokenPath, JSON.stringify(blob, null, 2), { mode: FILE_MODE });
|
|
4558
4770
|
},
|
|
4559
4771
|
load() {
|
|
4560
|
-
if (!
|
|
4772
|
+
if (!fs34.existsSync(tokenPath)) return null;
|
|
4561
4773
|
try {
|
|
4562
|
-
const blob = JSON.parse(
|
|
4774
|
+
const blob = JSON.parse(fs34.readFileSync(tokenPath, "utf8"));
|
|
4563
4775
|
if (!isEncryptedBlob(blob)) return null;
|
|
4564
4776
|
const { jwtToken, siteId } = JSON.parse(decrypt2(loadOrCreateKey(), blob).toString("utf8"));
|
|
4565
4777
|
return typeof jwtToken === "string" && jwtToken && typeof siteId === "string" ? { jwtToken, siteId } : null;
|
|
@@ -4571,7 +4783,7 @@ function createTokenStore(opts) {
|
|
|
4571
4783
|
}
|
|
4572
4784
|
logger.debug(`[harmonyos] Discarding unreadable token at ${tokenPath}.`);
|
|
4573
4785
|
try {
|
|
4574
|
-
|
|
4786
|
+
fs34.rmSync(tokenPath, { force: true });
|
|
4575
4787
|
} catch {
|
|
4576
4788
|
}
|
|
4577
4789
|
return null;
|
|
@@ -4579,7 +4791,7 @@ function createTokenStore(opts) {
|
|
|
4579
4791
|
},
|
|
4580
4792
|
clear() {
|
|
4581
4793
|
try {
|
|
4582
|
-
|
|
4794
|
+
fs34.rmSync(tokenPath, { force: true });
|
|
4583
4795
|
} catch (err) {
|
|
4584
4796
|
throw new OniroError(`Failed to remove ${tokenPath}.`, err);
|
|
4585
4797
|
}
|
|
@@ -5060,7 +5272,7 @@ function mapAgcError(operation, statusCode, reasonPhrase, body) {
|
|
|
5060
5272
|
}
|
|
5061
5273
|
|
|
5062
5274
|
// src/harmonyos/signing/profile.ts
|
|
5063
|
-
import * as
|
|
5275
|
+
import * as fs35 from "fs";
|
|
5064
5276
|
import { X509Certificate } from "crypto";
|
|
5065
5277
|
import forge from "node-forge";
|
|
5066
5278
|
function extractProfileJson(buffer) {
|
|
@@ -5092,7 +5304,7 @@ function extractProfileJson(buffer) {
|
|
|
5092
5304
|
function readProvisionProfile(profilePath) {
|
|
5093
5305
|
let raw;
|
|
5094
5306
|
try {
|
|
5095
|
-
const json = extractProfileJson(
|
|
5307
|
+
const json = extractProfileJson(fs35.readFileSync(profilePath));
|
|
5096
5308
|
if (!json) return null;
|
|
5097
5309
|
raw = JSON.parse(json);
|
|
5098
5310
|
} catch {
|
|
@@ -5121,7 +5333,7 @@ function parseCertificate(pem) {
|
|
|
5121
5333
|
}
|
|
5122
5334
|
function keystoreHoldsKey(p12Path, keyAlias, keyPwd, certificate) {
|
|
5123
5335
|
try {
|
|
5124
|
-
const der = forge.util.createBuffer(
|
|
5336
|
+
const der = forge.util.createBuffer(fs35.readFileSync(p12Path).toString("binary"));
|
|
5125
5337
|
const p12 = forge.pkcs12.pkcs12FromAsn1(forge.asn1.fromDer(der), keyPwd);
|
|
5126
5338
|
const certBag = forge.pki.oids.certBag ?? "1.2.840.113549.1.12.10.1.3";
|
|
5127
5339
|
const wanted = certificate.publicKey.export({ type: "spki", format: "der" });
|
|
@@ -5137,7 +5349,7 @@ function keystoreHoldsKey(p12Path, keyAlias, keyPwd, certificate) {
|
|
|
5137
5349
|
}
|
|
5138
5350
|
}
|
|
5139
5351
|
function verifySigningMaterial(opts) {
|
|
5140
|
-
const pems =
|
|
5352
|
+
const pems = fs35.readFileSync(opts.cerPath, "utf8").match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g);
|
|
5141
5353
|
const chain = (pems ?? []).map(parseCertificate);
|
|
5142
5354
|
const leaf = chain.find((c) => !c.ca) ?? chain.at(-1);
|
|
5143
5355
|
if (!leaf) throw new AgcError(SIGNING_ERRORS.CERT_INVALID);
|
|
@@ -5156,14 +5368,14 @@ function verifySigningMaterial(opts) {
|
|
|
5156
5368
|
|
|
5157
5369
|
// src/harmonyos/signing/autoSign.ts
|
|
5158
5370
|
import * as crypto9 from "crypto";
|
|
5159
|
-
import * as
|
|
5160
|
-
import * as
|
|
5371
|
+
import * as fs40 from "fs";
|
|
5372
|
+
import * as path39 from "path";
|
|
5161
5373
|
import JSON57 from "json5";
|
|
5162
5374
|
|
|
5163
5375
|
// src/harmonyos/signing/agc.ts
|
|
5164
5376
|
import * as crypto6 from "crypto";
|
|
5165
|
-
import * as
|
|
5166
|
-
import * as
|
|
5377
|
+
import * as fs36 from "fs";
|
|
5378
|
+
import * as path34 from "path";
|
|
5167
5379
|
var ENDPOINTS = {
|
|
5168
5380
|
CERT_LIST: "/api/cps/harmony-cert-manage/v1/cert/list",
|
|
5169
5381
|
CERT_ADD: "/api/cps/harmony-cert-manage/v1/cert/add",
|
|
@@ -5249,8 +5461,8 @@ function createAgcClient(http3, auth) {
|
|
|
5249
5461
|
if (target.sha256 && actual !== target.sha256.toLowerCase()) {
|
|
5250
5462
|
throw new ChecksumMismatchError(target.sha256, actual);
|
|
5251
5463
|
}
|
|
5252
|
-
|
|
5253
|
-
|
|
5464
|
+
fs36.mkdirSync(path34.dirname(dest), { recursive: true, mode: 448 });
|
|
5465
|
+
fs36.writeFileSync(dest, buffer, { mode: 384 });
|
|
5254
5466
|
}
|
|
5255
5467
|
};
|
|
5256
5468
|
}
|
|
@@ -5301,22 +5513,22 @@ async function registerDevices(agc, connected, logger) {
|
|
|
5301
5513
|
|
|
5302
5514
|
// src/harmonyos/signing/keystore.ts
|
|
5303
5515
|
import * as crypto7 from "crypto";
|
|
5304
|
-
import * as
|
|
5305
|
-
import * as
|
|
5516
|
+
import * as fs38 from "fs";
|
|
5517
|
+
import * as path36 from "path";
|
|
5306
5518
|
|
|
5307
5519
|
// src/harmonyos/java.ts
|
|
5308
|
-
import * as
|
|
5309
|
-
import * as
|
|
5520
|
+
import * as fs37 from "fs";
|
|
5521
|
+
import * as path35 from "path";
|
|
5310
5522
|
var JAVA_BIN = process.platform === "win32" ? "java.exe" : "java";
|
|
5311
5523
|
function findJava(sdk, env = process.env) {
|
|
5312
5524
|
const candidates = [
|
|
5313
|
-
env.JAVA_HOME &&
|
|
5314
|
-
sdk &&
|
|
5525
|
+
env.JAVA_HOME && path35.join(env.JAVA_HOME, "bin", JAVA_BIN),
|
|
5526
|
+
sdk && path35.join(sdk.installRoot, "jbr", "bin", JAVA_BIN),
|
|
5315
5527
|
// macOS: the JBR is itself a bundle inside Studio's Contents.
|
|
5316
|
-
sdk &&
|
|
5317
|
-
...(env.PATH ?? "").split(
|
|
5528
|
+
sdk && path35.join(sdk.installRoot, "jbr", "Contents", "Home", "bin", JAVA_BIN),
|
|
5529
|
+
...(env.PATH ?? "").split(path35.delimiter).map((dir) => dir && path35.join(dir, JAVA_BIN))
|
|
5318
5530
|
];
|
|
5319
|
-
const found = candidates.find((c) => !!c &&
|
|
5531
|
+
const found = candidates.find((c) => !!c && fs37.existsSync(c));
|
|
5320
5532
|
if (found) return found;
|
|
5321
5533
|
throw new OniroError(
|
|
5322
5534
|
"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."
|
|
@@ -5330,13 +5542,13 @@ function redactArgs(args) {
|
|
|
5330
5542
|
return args.map((arg, i) => args[i - 1] === "-keyPwd" || args[i - 1] === "-keystorePwd" ? "******" : arg);
|
|
5331
5543
|
}
|
|
5332
5544
|
async function generateKeystoreAndCsr(opts) {
|
|
5333
|
-
const jar =
|
|
5334
|
-
if (!
|
|
5545
|
+
const jar = path36.join(opts.sdk.sdkPath, "default", "openharmony", "toolchains", "lib", "hap-sign-tool.jar");
|
|
5546
|
+
if (!fs38.existsSync(jar)) {
|
|
5335
5547
|
throw new OniroError(`hap-sign-tool.jar not found at ${jar}; the HarmonyOS SDK looks incomplete.`);
|
|
5336
5548
|
}
|
|
5337
5549
|
const java = findJava(opts.sdk);
|
|
5338
5550
|
const keyPwd = crypto7.randomBytes(12).toString("base64url").replaceAll(/[-_]/g, "");
|
|
5339
|
-
|
|
5551
|
+
fs38.mkdirSync(path36.dirname(opts.p12Path), { recursive: true, mode: 448 });
|
|
5340
5552
|
const run = async (what, args) => {
|
|
5341
5553
|
const argv = ["-jar", jar, ...args, "-keyAlias", KEY_ALIAS, "-keystoreFile", opts.p12Path, "-keystorePwd", keyPwd, "-keyPwd", keyPwd];
|
|
5342
5554
|
opts.logger.debug(`[harmonyos] ${java} ${redactArgs(argv).join(" ")}`);
|
|
@@ -5350,28 +5562,28 @@ ${detail}` : ""}`);
|
|
|
5350
5562
|
opts.logger.info("[harmonyos] Generating the local keystore and certificate signing request...");
|
|
5351
5563
|
await run("generate the key pair", ["generate-keypair", "-keyAlg", "ECC", "-keySize", "NIST-P-256"]);
|
|
5352
5564
|
await run("generate the CSR", ["generate-csr", "-subject", "CN=DebugKey", "-signAlg", SIGN_ALG, "-outFile", opts.csrPath]);
|
|
5353
|
-
return { keyPwd, csr:
|
|
5565
|
+
return { keyPwd, csr: fs38.readFileSync(opts.csrPath, "utf8") };
|
|
5354
5566
|
}
|
|
5355
5567
|
|
|
5356
5568
|
// src/harmonyos/signing/paths.ts
|
|
5357
5569
|
import * as crypto8 from "crypto";
|
|
5358
|
-
import * as
|
|
5570
|
+
import * as path37 from "path";
|
|
5359
5571
|
function sanitizeNamePart(raw) {
|
|
5360
5572
|
const safe = (raw?.trim() ?? "").replace(/[\\/:*?"<>|=.-]+/g, "_");
|
|
5361
5573
|
return safe.slice(0, 64) || "default";
|
|
5362
5574
|
}
|
|
5363
5575
|
function resolveSigningMaterialPaths(config, productName, projectRoot) {
|
|
5364
5576
|
const hash = crypto8.createHash("sha256").update(projectRoot, "utf8").digest("base64url").replaceAll(/[-_]/g, "");
|
|
5365
|
-
const base =
|
|
5577
|
+
const base = path37.join(
|
|
5366
5578
|
config.get("harmonyosSigningDir", defaultPaths.harmonyosSigningDir()),
|
|
5367
|
-
`${sanitizeNamePart(productName)}_${
|
|
5579
|
+
`${sanitizeNamePart(productName)}_${path37.basename(projectRoot)}_${hash}=`
|
|
5368
5580
|
);
|
|
5369
5581
|
return { p12Path: `${base}.p12`, csrPath: `${base}.csr`, cerPath: `${base}.cer`, profilePath: `${base}.p7b` };
|
|
5370
5582
|
}
|
|
5371
5583
|
|
|
5372
5584
|
// src/harmonyos/signing/project.ts
|
|
5373
|
-
import * as
|
|
5374
|
-
import * as
|
|
5585
|
+
import * as fs39 from "fs";
|
|
5586
|
+
import * as path38 from "path";
|
|
5375
5587
|
import JSON56 from "json5";
|
|
5376
5588
|
|
|
5377
5589
|
// src/harmonyos/signing/aclPermissionList.ts
|
|
@@ -5439,9 +5651,9 @@ var ACL_PERMISSIONS = /* @__PURE__ */ new Set([
|
|
|
5439
5651
|
|
|
5440
5652
|
// src/harmonyos/signing/project.ts
|
|
5441
5653
|
function readRequestedPermissions(moduleConfigPath) {
|
|
5442
|
-
if (!
|
|
5654
|
+
if (!fs39.existsSync(moduleConfigPath)) return [];
|
|
5443
5655
|
try {
|
|
5444
|
-
const parsed = JSON56.parse(
|
|
5656
|
+
const parsed = JSON56.parse(fs39.readFileSync(moduleConfigPath, "utf-8"));
|
|
5445
5657
|
return (parsed.module?.requestPermissions ?? []).map((p) => p?.name).filter((n) => typeof n === "string" && n.length > 0);
|
|
5446
5658
|
} catch {
|
|
5447
5659
|
return [];
|
|
@@ -5450,10 +5662,10 @@ function readRequestedPermissions(moduleConfigPath) {
|
|
|
5450
5662
|
function collectAclPermissions(projectDir, logger = noopLogger) {
|
|
5451
5663
|
const requested = /* @__PURE__ */ new Set();
|
|
5452
5664
|
for (const module of listModules({ projectDir })) {
|
|
5453
|
-
const moduleRoot =
|
|
5665
|
+
const moduleRoot = path38.resolve(projectDir, module.srcPath);
|
|
5454
5666
|
for (const sourceSet of ["main", "ohosTest"]) {
|
|
5455
5667
|
for (const name of readRequestedPermissions(
|
|
5456
|
-
|
|
5668
|
+
path38.join(moduleRoot, "src", sourceSet, "module.json5")
|
|
5457
5669
|
)) {
|
|
5458
5670
|
requested.add(name);
|
|
5459
5671
|
}
|
|
@@ -5469,7 +5681,7 @@ function collectAclPermissions(projectDir, logger = noopLogger) {
|
|
|
5469
5681
|
// src/harmonyos/signing/autoSign.ts
|
|
5470
5682
|
function shouldRegenerate(input) {
|
|
5471
5683
|
if (input.force) return "--force was passed";
|
|
5472
|
-
const missing = Object.values(input.paths).find((file) => !
|
|
5684
|
+
const missing = Object.values(input.paths).find((file) => !fs40.existsSync(file));
|
|
5473
5685
|
if (missing) return `${missing} is missing`;
|
|
5474
5686
|
const config = input.buildProfile.app?.signingConfigs?.find((c) => c.name === input.productName);
|
|
5475
5687
|
if (config?.type !== "HarmonyOS" || config.material?.profile !== input.paths.profilePath) {
|
|
@@ -5508,16 +5720,16 @@ function writeSigningConfig(opts) {
|
|
|
5508
5720
|
for (const product of app.products ?? []) {
|
|
5509
5721
|
if (product.name === opts.productName) product.signingConfig = opts.productName;
|
|
5510
5722
|
}
|
|
5511
|
-
|
|
5723
|
+
fs40.writeFileSync(opts.buildProfilePath, JSON.stringify(opts.buildProfile, null, 2));
|
|
5512
5724
|
}
|
|
5513
5725
|
async function harmonyOsAutoSign(opts) {
|
|
5514
5726
|
const logger = opts.logger ?? noopLogger;
|
|
5515
5727
|
const productName = opts.productName ?? "default";
|
|
5516
|
-
const projectDir =
|
|
5517
|
-
const buildProfilePath =
|
|
5728
|
+
const projectDir = path39.resolve(opts.projectDir);
|
|
5729
|
+
const buildProfilePath = path39.join(projectDir, "build-profile.json5");
|
|
5518
5730
|
let buildProfile;
|
|
5519
5731
|
try {
|
|
5520
|
-
buildProfile = JSON57.parse(
|
|
5732
|
+
buildProfile = JSON57.parse(fs40.readFileSync(buildProfilePath, "utf-8"));
|
|
5521
5733
|
} catch (err) {
|
|
5522
5734
|
throw new OniroError(`Could not read ${buildProfilePath}: ${err.message}`, err);
|
|
5523
5735
|
}
|
|
@@ -5557,7 +5769,7 @@ async function harmonyOsAutoSign(opts) {
|
|
|
5557
5769
|
logger.info(`[harmonyos] Regenerating signing material: ${reason}.`);
|
|
5558
5770
|
const agc = createAgcClient(opts.http ?? createHttpClient({ logger }), auth);
|
|
5559
5771
|
const deviceIds = await registerDevices(agc, connected, logger);
|
|
5560
|
-
for (const file of Object.values(paths))
|
|
5772
|
+
for (const file of Object.values(paths)) fs40.rmSync(file, { force: true });
|
|
5561
5773
|
const certName = `oniro_debug_${auth.teamId.replace(/[\\/.:]/g, "")}.cer`;
|
|
5562
5774
|
const stale = (await agc.listCertificates()).find((c) => c.certName === certName);
|
|
5563
5775
|
if (stale) {
|
|
@@ -5588,10 +5800,10 @@ async function harmonyOsAutoSign(opts) {
|
|
|
5588
5800
|
try {
|
|
5589
5801
|
verifySigningMaterial({ ...paths, keyAlias: KEY_ALIAS, keyPwd });
|
|
5590
5802
|
} catch (err) {
|
|
5591
|
-
|
|
5803
|
+
fs40.rmSync(paths.profilePath, { force: true });
|
|
5592
5804
|
throw err;
|
|
5593
5805
|
}
|
|
5594
|
-
const materialDir =
|
|
5806
|
+
const materialDir = path39.join(path39.dirname(paths.p12Path), "material");
|
|
5595
5807
|
try {
|
|
5596
5808
|
getKey(materialDir);
|
|
5597
5809
|
} catch {
|
|
@@ -5603,7 +5815,7 @@ async function harmonyOsAutoSign(opts) {
|
|
|
5603
5815
|
}
|
|
5604
5816
|
|
|
5605
5817
|
// src/index.ts
|
|
5606
|
-
var VERSION = "0.
|
|
5818
|
+
var VERSION = "0.15.0";
|
|
5607
5819
|
export {
|
|
5608
5820
|
ALL_SDKS,
|
|
5609
5821
|
APL_VALUES,
|
|
@@ -5617,6 +5829,7 @@ export {
|
|
|
5617
5829
|
HUAWEI_SITES,
|
|
5618
5830
|
INSTALL_TMP_DIRNAME,
|
|
5619
5831
|
InsufficientSpaceError,
|
|
5832
|
+
OHOS_DAILY_BUILDS_URL,
|
|
5620
5833
|
OHOS_URL_BASE,
|
|
5621
5834
|
OniroError,
|
|
5622
5835
|
SIGNING_ERRORS,
|
|
@@ -5637,6 +5850,7 @@ export {
|
|
|
5637
5850
|
buildHvigorwArgs,
|
|
5638
5851
|
buildInputCommand,
|
|
5639
5852
|
buildRawTouchCommand,
|
|
5853
|
+
bundleNameFromHapConfig,
|
|
5640
5854
|
captureBurst,
|
|
5641
5855
|
captureLog,
|
|
5642
5856
|
cleanCodelinterOutput,
|
|
@@ -5690,6 +5904,7 @@ export {
|
|
|
5690
5904
|
findLayoutNodes,
|
|
5691
5905
|
findMissingProjectSdk,
|
|
5692
5906
|
findRunningProcess,
|
|
5907
|
+
findSdkOsDir,
|
|
5693
5908
|
flattenLayout,
|
|
5694
5909
|
forceStop,
|
|
5695
5910
|
formatBytes,
|
|
@@ -5723,10 +5938,12 @@ export {
|
|
|
5723
5938
|
hdcTargetArgs,
|
|
5724
5939
|
hdcTargetArgsFor,
|
|
5725
5940
|
hideKeyboard,
|
|
5941
|
+
hilogTimeMs,
|
|
5726
5942
|
installApp,
|
|
5727
5943
|
installCmdTools,
|
|
5728
5944
|
installEmulator,
|
|
5729
5945
|
installFailureReason,
|
|
5946
|
+
installSdkFromArchive,
|
|
5730
5947
|
isBundleInstalled,
|
|
5731
5948
|
isCmdToolsInstalled,
|
|
5732
5949
|
isEmulatorInstalled,
|
|
@@ -5743,6 +5960,7 @@ export {
|
|
|
5743
5960
|
listRunningProcesses,
|
|
5744
5961
|
listTemplates,
|
|
5745
5962
|
locateTarget,
|
|
5963
|
+
missingProjectRootFiles,
|
|
5746
5964
|
needsCmdWrapper,
|
|
5747
5965
|
nonInteractivePrompter,
|
|
5748
5966
|
noopLogger,
|
|
@@ -5766,9 +5984,11 @@ export {
|
|
|
5766
5984
|
pickTarget,
|
|
5767
5985
|
prepareSigning,
|
|
5768
5986
|
pruneLayout,
|
|
5987
|
+
readHapBundleName,
|
|
5769
5988
|
readJson5File,
|
|
5770
5989
|
readJsonFile,
|
|
5771
5990
|
readProvisionProfile,
|
|
5991
|
+
readZipEntry,
|
|
5772
5992
|
reboot,
|
|
5773
5993
|
recvFile,
|
|
5774
5994
|
removeCmdTools,
|